home *** CD-ROM | disk | FTP | other *** search
-
- ;┌───────────────────────────────────────────────────────────────────┐
- ;│ │
- ;│ █████ █ █ █▀▀▀█ █▀▀▄ ▀▀█▀▀ ▄▀▀▀▄ █▀▀▀▀ │
- ;│ █ ██ ██ █ █ █ █ █ █ █ █ │
- ;│ █████ █ █ █ ▀▀▀▀▀ █████ ████ █ █ █ █████ │
- ;│ █ █ █ █ █ █ █ █ █ █ █ │
- ;│ █████ █ █ █ █ █▄▄▀ ▄▄█▄▄ ▀▄▄▄▀ █████ │
- ;│ │
- ;│ │
- ;│ 2M-ABIOS 1.3 - (C) 1994-1995 Ciriaco García de Celis. │
- ;│ │
- ;│ Código para emular al 100% la BIOS AMI de 1993. │
- ;│ │
- ;│ Si el ordenador posee disco duro y una BIOS moderna, la │
- ;│ INT 40h controla los accesos a disquete. Desviar esta │
- ;│ interrupción en lugar de la INT 13h permite que este │
- ;│ programa tome el control de las disqueteras antes que │
- ;│ cualquier otro (incluso aunque se instale después) y │
- ;│ además permite seguir trabajando al código del DOS que, │
- ;│ desde INT 13h, soluciona el cruce con las fronteras de │
- ;│ DMA antes de invocar a la INT 40h. │
- ;│ │
- ;│ Si el ordenador no utilizase la INT 40h en los accesos a │
- ;│ las disqueteras se desvía INT 13h y se cuelga este código │
- ;│ de la misma, cuidando evitar un cruce con el DMA a través │
- ;│ de un buffer intermedio auxiliar si es preciso. │
- ;│ │
- ;│ Para la versión AT: Para la versión PC/XT: │
- ;│ TASM 2m-abios /m5 TASM 2m-abios, 2m-xbios /m5 /dXT │
- ;│ TLINK 2m-abios TLINK 2m-xbios │
- ;│ │
- ;│ Con [+] se señalizan las líneas del listado que cambian │
- ;│ de manera intencionada y por algún motivo especial │
- ;│ respecto a la BIOS AMI original (entre otras no señaladas │
- ;│ por no tener un motivo tan especial de cambio). │
- ;│ │
- ;└───────────────────────────────────────────────────────────────────┘
-
- IFDEF XT
- ID EQU ,"X",
- ELSE
- .286 ; versión para AT o superior
- ID EQU ,"A",
- ENDIF
-
- ; ------------ Macros de propósito general.
-
- XPUSH MACRO regmem ; apilar lista de registros
- IRP rm, <regmem>
- PUSH rm
- ENDM
- ENDM
-
- XPOP MACRO regmem ; desapilar lista de registros
- IRP rm, <regmem>
- POP rm
- ENDM
- ENDM
-
- IFNDEF XT
-
- XPUSHA MACRO
- PUSHA
- ENDM
-
- XPOPA MACRO
- POPA
- ENDM
-
- XSHR MACRO regmem, cuenta
- SHR regmem,cuenta
- ENDM
-
- XSHL MACRO regmem, cuenta
- SHL regmem,cuenta
- ENDM
-
- XROR MACRO regmem, cuenta
- ROR regmem,cuenta
- ENDM
-
- XROL MACRO regmem, cuenta
- ROL regmem,cuenta
- ENDM
-
- DDS MACRO
- PUSH 40h
- POP DS
- ENDM
-
- ELSE
-
- XPUSHA MACRO
- XPUSH <AX, BX, CX, DX, SI, DI>
- ENDM
-
- XPOPA MACRO
- XPOP <DI, SI, DX, CX, BX, AX>
- ENDM
-
- XSHR MACRO regmem, cuenta
- REPT cuenta
- SHR regmem,1
- ENDM
- ENDM
-
- XSHL MACRO regmem, cuenta
- REPT cuenta
- SHL regmem,1
- ENDM
- ENDM
-
- XROR MACRO regmem, cuenta
- REPT cuenta
- ROR regmem,1
- ENDM
- ENDM
-
- XROL MACRO regmem, cuenta
- REPT cuenta
- ROL regmem,1
- ENDM
- ENDM
-
- DDS MACRO
- PUSH AX
- MOV AX,40h
- MOV DS,AX
- POP AX
- ENDM
-
- ENDIF
-
- ; ************ Inicio del área residente.
-
- _PRINCIPAL SEGMENT
- ASSUME CS:_PRINCIPAL, DS:_PRINCIPAL
-
- ORG 0
-
- ini_residente EQU $
-
- DD -1 ; encadenamiento con otros drivers
- tipo_drive DW 8000h ; palabra de atributo:
- ; bit 15 a 1: dispositivo caracteres
- ; bit 14 a 0: sin control IOCTL
- DW estrategia ; rutina de estrategia
- DW interrupcion ; rutina de interrupción
- DB "2M-BIOS$" ; nombre del dispositivo
-
- estrategia PROC FAR
- MOV CS:pcab_pet_segm,ES
- MOV CS:pcab_pet_desp,BX
- RET
- estrategia ENDP
-
- interrupcion PROC FAR
- CALL main ; tras instalar: XPUSH <DS, BX> y MOV BX,??
- pcab_pet_segm DW ?
- MOV DS,BX
- DB 0BBh ; opcode de MOV BX,??
- pcab_pet_desp DW ?
- MOV WORD PTR [BX+3],8103h ; código de error
- XPOP <BX, DS>
- RET
- interrupcion ENDP
-
- ; ****************************************
- ; * *
- ; * D A T O S R E S I D E N T E S *
- ; * *
- ; ****************************************
-
- ; ------------ Identificación estandarizada del programa.
-
- program_id LABEL BYTE
- segmento_real DW 0 ; segmento real donde será cargado
- offset_real DW 0 ; offset real " " "
- longitud_total DW 0 ; zona de memoria ocupada (párrafos)
- info_extra DB 03h ; bits 0, 1 y 2-> 000: normal, con PSP
- ; 001: bloque UMB XMS
- ; 010: *.SYS
- ; 011: *.SYS formato EXE
- ; bit 7 a 1: «extension_id» definida
- multiplex_id DB 0 ; número Multiplex de este TSR
- vectores_id DW tabla_vectores
- extension_id DW 0
- DB "*##*"
- autor_nom_ver DB "CiriSOFT:2M-" ID "BIOS:1.3",0
-
- DB 3 ; número de vectores de interrupción usados
- tabla_vectores EQU $
- DB 15h ; INT 15h
- ant_int15 LABEL DWORD ; dirección original
- ant_int15_off DW 0
- ant_int15_seg DW 0
- DB 2Fh ; INT 2Fh
- ant_int2F LABEL DWORD ; dirección original
- ant_int2F_off DW 0
- ant_int2F_seg DW 0
- DB 40h ; INT 40h
- ant_int40 LABEL DWORD ; dirección original
- ant_int40_off DW 0
- ant_int40_seg DW 0
- DB 13h ; INT 13h podría llegar a usarse
- ant_int13 LABEL DWORD
- ant_int13_off DW 0
- ant_int13_seg DW 0
-
- ; ***************************************
- ; * *
- ; * C O D I G O R E S I D E N T E *
- ; * *
- ; ***************************************
-
- ; ------------ Rutina de gestión de INT 2Fh.
-
- ges_int2F PROC FAR
- STI
- CMP AH,CS:multiplex_id
- JE preguntan
- JMP CS:ant_int2F ; saltar al gestor de INT 2Fh
- preguntan: CMP DI,1992h
- JNE ret_no_info ; no llama alguien del convenio
- MOV AX,ES
- CMP AX,1492h
- JNE ret_no_info ; no llama alguien del convenio
- PUSH CS
- POP ES ; sí llama: darle información
- LEA DI,autor_nom_ver
- ret_no_info: MOV AX,0FFFFh ; "entrada multiplex en uso"
- IRET
- ges_int2F ENDP
-
- ; ------------ Rutina de gestión de INT 15h.
-
- ges_int15 PROC FAR
- STI
- CMP AX,90FDh
- JE ret_clc
- CMP AX,9001h
- JE ret_clc
- JMP CS:ant_int15
- ret_clc: CLC
- RET 2
- ges_int15 ENDP
-
- ; ------------ Rutina de control de INT 40h.
-
- r_flags EQU WORD PTR [BP+18h] ; constantes para parámetros
- r_flags_l EQU BYTE PTR [BP+18h]
- r_flags_h EQU BYTE PTR [BP+19h]
- r_ax EQU WORD PTR [BP+12h]
- r_al EQU BYTE PTR [BP+12h]
- r_ah EQU BYTE PTR [BP+13h]
- r_cx EQU WORD PTR [BP+10h]
- r_cl EQU BYTE PTR [BP+10h]
- r_ch EQU BYTE PTR [BP+11h]
- r_dx EQU WORD PTR [BP+0Eh]
- r_dl EQU BYTE PTR [BP+0Eh]
- r_dh EQU BYTE PTR [BP+0Fh]
- r_bx EQU WORD PTR [BP+0Ch]
- r_bl EQU BYTE PTR [BP+0Ch]
- r_bh EQU BYTE PTR [BP+0Dh]
- r_bp EQU WORD PTR [BP+0Ah]
- r_si EQU WORD PTR [BP+08h]
- r_di EQU WORD PTR [BP+06h]
- r_ds EQU WORD PTR [BP+04h]
- r_es EQU WORD PTR [BP+02h]
-
- ges_int40 PROC
- STI
- CLD
- PUSH AX
- PUSH CX
- PUSH DX
- PUSH BX
- PUSH BP
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH ES
- PUSH BP
- MOV BP,SP
- DDS
- PUSH AX
- MOV AL,AH
- CMP AL,18h
- JA mal_funcion
- CMP AL,5
- JBE func_oper
- CMP AL,8
- JNE func_aux?
- MOV AL,6
- JMP func_oper
- func_aux?: CMP AL,15h
- JB mal_funcion
- SUB AL,0Eh
- func_oper: CBW
- MOV DI,AX
- POP AX
- SHL DI,1
- JMP CS:tab_jmp[DI] ; ejecutar función
- main_exit: MOV AL,AH ; preservar resultado
- LAHF ; preservar flags
- PUSH AX
- DDS
- MOV AL,r_dl ; DL a la llamada (unidad)
- CMP AL,1
- JA u_det ; unidad incorrecta
- XOR AH,AH
- MOV BX,90h
- ADD BX,AX ; [BX] -> estado físico unidad
- TEST BYTE PTR DS:[BX],10h ; ¿densidad determinada?
- JZ u_det ; no
- MOV DL,4 ; sí
- MUL DL
- MOV CL,AL
- SHL DL,CL
- OR DS:[8Fh],DL ; unidad determinada
- u_det: POP AX
- SAHF ; recuperar flags
- MOV AH,AL ; recuperar resultado
- exit_i40: MOV r_ah,AH ; AH para la salida del IRET
- MOV AX,201H ; STI + STC en flags
- JC set_err ; hay error
- AND r_flags_l,0FEH ; CLC (si no hay error)
- DEC AX ; dejar sólo STI
- set_err: OR r_flags,AX ; flags a la salida del IRET
- POP BP
- POP ES
- POP DS
- POP DI
- POP SI
- POP BP
- POP BX
- POP DX
- POP CX
- POP AX ; registros con resultado
- IRET
- ges_int40 ENDP
-
- mal_funcion: POP AX
- MOV AH,1 ; función/parámetro incorrecto
- MOV DS:[41h],AH ; código de error
- STC ; condición de error
- JMP exit_i40
-
- ; ------------ Función 0: Resetear el sistema de disco.
-
- reset PROC
- CALL full_init ; inicialización plena
- MOV DS:[41h],AH ; código de error
- MOV AL,AH ; preservar código
- LAHF ; preservar flags
- PUSH AX
- PUSH DS
- XOR SI,SI
- MOV DS,SI
- LDS SI,DWORD PTR DS:[78h] ; DS:SI -> INT 1Eh
- MOV CL,[SI+2]
- POP DS
- MOV DS:[40h],CL ; tics para detención motor
- POP AX
- SAHF
- MOV AH,AL ; restaurado código y flags
- JMP exit_i40
- reset ENDP
-
- ; ------------ Inicialización plena.
-
- full_init PROC
- AND BYTE PTR DS:[3Eh],0F0h ; futuro recalibramiento
- JMP init_fdc ; inicializar FDC
- fdc_init: JC init_end
- JMP send_specify ; enviar specify
- specify_sent: JC init_end
- XOR AH,AH ; no hay error
- init_end: RET
- full_init ENDP
-
- ; ------------ Función 1: Obtener resultado de la última operación.
-
- get_status PROC
- MOV AH,DS:[41h]
- OR AH,AH
- JZ no_err
- STC
- no_err: JMP exit_i40
- get_status ENDP
-
- ; ------------ Función 15h: Obtener el tipo de disco.
-
- get_disk_type PROC
- CMP DL,1
- JBE gdt_ok
- MOV AH,1 ; función/parámetro incorrecto
- STC
- MOV DS:[41h],AH ; código de error
- JMP gdt_exit
- gdt_ok: MOV BX,90h
- XOR DH,DH
- ADD BX,DX ; [BX] -> estado físico unidad
- MOV BL,[BX] ; estado físico de la unidad
- OR BL,BL
- JNZ gdt_posible
- XOR AH,AH ; no existe tal unidad
- JMP gdt_bye
- gdt_posible: AND BL,7
- JZ gdt_without ; 360K
- CMP BL,3
- JE gdt_without ; 360K
- CALL get_drive_type ; [+] Tipo disquetera en AL
- CMP AL,3 ; [+] sin soporte cambio en 720
- JE gdt_without ; [+] Bug en BIOS AMI original?
- MOV AH,2
- JMP gdt_bye ; con soporte cambio de línea
- gdt_without: MOV AH,1 ; sin soporte cambio de línea
- gdt_bye: CLC
- MOV BYTE PTR DS:[41h],0 ; siempre sin error
- gdt_exit: JMP main_exit
- get_disk_type ENDP
-
- ; ------------ Función 17h: Establecer tipo de soporte para formateo.
-
- set_type_fmt PROC
- XOR AH,AH
- CMP DL,1
- JBE set_tp
- set_tp_bad_p: MOV AH,1 ; función/parámetro incorrecto
- set_tp_err: MOV DS:[41h],AH ; código de error
- STC
- JMP set_tp_exit
- set_tp: CMP AL,0 ; validar parámetro
- JE set_tp_bad_p
- CMP AL,4
- JA set_tp_bad_p
- MOV BX,90h
- XOR DH,DH
- ADD BX,DX ; [BX] -> estado físico unidad
- CMP AL,1 ; ¿360K en 360K?
- JNE set_tp_n360
- MOV BYTE PTR DS:[BX],93h ; actualizar variable tipo
- MOV BYTE PTR DS:[41h],0 ; anular errores previos
- JMP set_tp_t_exit
- set_tp_n360: MOV CX,AX
- PUSH BX
- CALL motor_on ; arrancar motor
- POP SI
- PUSH SI
- CALL read_disk_chg ; ¿cambio de disco?
- POP BX
- CMP AH,6 ; (0: no, 6: sí)
- JBE set_tp_cd ; haya cambio o no
- CMP AH,80h
- JNE set_tp_cd ; sí existe disco
- CMP BYTE PTR DS:[BX],97h ; ¿250 Kbps y no es 5.25?
- JE set_tp_err ; error
- MOV BYTE PTR DS:[BX],61h ; 300 Kbps, try 360 en 1.2
- JMP set_tp_err ; error
- set_tp_cd: CMP CL,4 ; ¿720K en 720K?
- JNE set_tp_n720 ; no
- MOV BYTE PTR DS:[BX],97h ; actualizar variable tipo
- JMP set_tp_t_exit
- set_tp_n720: CMP CL,2 ; ¿360K en 1.2M?
- JNE set_tp_ndd ; no
- MOV BYTE PTR DS:[BX],74h ; actualizar variable tipo
- JMP set_tp_t_exit
- set_tp_ndd: MOV BYTE PTR DS:[BX],15h ; 1.2M en 1.2M
- set_tp_t_exit: OR AH,AH ; comprobar posible error
- JNZ set_tp_err
- MOV BYTE PTR DS:[41h],0
- set_tp_exit: JMP main_exit
- set_type_fmt ENDP
-
- ; ------------ Función 16h: Detectar cambio de disco.
-
- detect_change PROC
- CMP DL,1
- JBE det_ch
- MOV AH,1 ; función/parámetro incorrecto
- det_ch_r_err: STC
- JMP det_ch_end
- det_ch: XOR DH,DH
- MOV BX,90h
- ADD BX,DX ; [BX] -> estado físico
- CMP BYTE PTR DS:[BX],0 ; ¿estado indeterminado?...
- MOV AH,80h ; "unidad no preparada"
- JE det_ch_r_err ; ...en efecto
- MOV AH,[BX]
- AND AH,7
- JZ det_ch_yes ; 360K en 360K, no es posible
- CMP AH,3
- JE det_ch_yes ; no es 360K en 360K
- CALL get_drive_type ; [+] Tipo disquetera en AL
- CMP AL,3 ; [+] sin soporte cambio en 720
- JNE det_ch_calc ; [+] Bug en BIOS AMI original?
- det_ch_yes: MOV AH,6 ; hay cambio (o desconocido)
- STC
- JMP det_ch_end
- det_ch_calc: CALL motor_on ; arrancar motor
- MOV DX,3F7h
- IN AL,DX ; leer línea de cambio de disco
- SHL AL,1
- JC det_ch_yes ; hay cambio de disco
- XOR AH,AH ; no lo hay
- det_ch_end: MOV DS:[41h],AH ; actualizar código de error
- PUSH AX
- PUSH SI
- PUSH DS
- MOV SI,0
- MOV DS,SI
- LDS SI,DWORD PTR DS:[78h] ; DS:SI -> INT 1Eh
- MOV AL,[SI+2]
- POP DS
- MOV DS:[40h],AL ; tiempo detención motor
- POP SI
- POP AX
- JMP main_exit
- detect_change ENDP
-
- ; ------------ Funciones 2, 3 y 4: Leer, escribir y verificar.
-
- read_wr_verify PROC
- CMP DL,1
- JBE rwv_posible
- MOV AH,1 ; función/parámetro incorrecto
- rwv_err: MOV DS:[41h],AH ; código de error
- XOR AL,AL
- STC
- JMP rwv_exit
- rwv_posible: MOV SI,90h
- PUSH DX
- XOR DH,DH
- ADD SI,DX ; [SI] -> estado físico
- CMP BYTE PTR DS:[SI],0 ; ¿estado indeterminado?...
- POP DX
- JNE rwv_state_ok ; no
- PUSH AX
- CALL get_drive_type ; obtener tipo disquetera en AL
- JZ rwv_type_ok ; ha resultado posible
- POP AX
- rwv_not_ready: MOV AH,80h ; "unidad no preparada"
- JMP rwv_err
- rwv_type_ok: OR AL,AL ; ¿existe la unidad?
- POP AX
- JZ rwv_not_ready ; no existe esa unidad
- MOV BYTE PTR DS:[SI],2 ; probando 1.2M en 1.2M
- rwv_state_ok: MOV DI,3Fh
- AND BYTE PTR DS:[DI],7Fh ; operación Read/Verify
- CMP AH,3 ; ¿operación de escritura?
- JNE rwv_nowr
- OR BYTE PTR DS:[DI],80h ; operación Write/Format
- rwv_nowr: PUSH SI
- CALL get_drive_type ; obtener tipo disquetera en AL
- JNZ rwv_media_ok
- CMP AL,1
- JE rwv_set360 ; es de 360K
- CMP AL,3
- JNE rwv_media_ok ; no es de 720K
- MOV BYTE PTR DS:[SI],97h ; forzar medio de 720K
- JMP rwv_media_ok
- rwv_set360: MOV BYTE PTR DS:[SI],93h ; forzar medio de 360K
- rwv_media_ok: CALL motor_on ; arrancar motores
- CALL read_disk_chg ; leer línea de cambio de disco
- POP SI
- JNC rwv_no_dschg ; no hay cambio de disco
- rwv_end_err: CALL end_io_access
- JMP rwv_err
- rwv_no_dschg: TEST BYTE PTR DS:[SI],10h ; ¿densidad determinada?
- JNZ rwv_set_rate ; en efecto
- CALL detect_media ; pues determinarla
- JC rwv_end_err ; problemas
- JMP rwv_dens_ok
- rwv_set_rate: CALL select_rate ; seleccionar la velocidad
- rwv_dens_ok: MOV SI,90h
- PUSH DX
- XOR DH,DH
- ADD SI,DX ; [SI] -> estado físico unidad
- POP DX
- MOV AX,0AF03H ; AF byte 0 specify 2.88
- CMP BYTE PTR DS:[SI],0D7h ; ¿2.88M?
- JE rwv_spec_ok ; así es
- MOV AX,0DF03h ; DF para 360/1.2/720
- CMP BYTE PTR DS:[SI],17h ; ¿1.44M?
- JNE rwv_spec_ok ; no
- MOV AH,0BFh ; sí
- rwv_spec_ok: MOV SI,AX ; SI 0-7: orden specify
- MOV DI,2 ; DI 0-7: byte 1 specify
- MOV CH,3 ; comando de 3 bytes
- OR BYTE PTR DS:[3Eh],80h ; no esperar INT
- CALL exec_cmd
- JC rwv_end_err ; fallo
- MOV AX,r_ax
- XOR AH,AH
- PUSH DS
- XOR SI,SI
- MOV DS,SI
- LDS SI,DWORD PTR DS:[78h] ; DS:SI -> INT 1Eh
- MOV CL,r_AL ; [+]
- ADD CL,r_CL ; [+] último sector a acceder
- DEC CL
- CMP CL,[SI+4] ; [+] fix por si el DOS está
- JBE rwv_usok ; [+] atontado
- MOV [SI+4],CL ; [+]
- rwv_usok: MOV CL,[SI+3] ; bytes/sector
- SHL AL,CL ; multiplicar por nº sectores
- MOV CL,80h
- MUL CL ; y por 128
- POP DS
- DEC AX ; un byte menos...
- MOV CX,AX ; ...cuenta para el DMA
- CALL eval_dir_DMA
- JNC rwv_dma_ok ; no hay problemas con el DMA
- MOV CX,r_cx ; restaurar CX
- JMP rwv_end_err ; problemas con el DMA
- rwv_dma_ok: MOV AX,r_ax
- CMP AH,2 ; ¿operación de lectura?
- JNE rwv_no_read
- MOV AH,46h ; byte de modo DMA para lectura
- JMP rwv_dma_set
- rwv_no_read: CMP AH,3 ; ¿escritura?
- MOV AH,4Ah ; modo DMA para escritura
- JZ rwv_dma_set
- MOV AH,42h ; modo DMA para verificación
- rwv_dma_set: CALL set_dma ; preparar DMA
- MOV AX,r_ax
- MOV CX,r_cx ; restaurar parámetros
- JMP perform_io ; efectuar E/S
- io_performed: CALL end_io_access
- OR AL,AL
- JZ rwv_end
- SUB BL,CL ; próximo sector-sector inicial
- MOV AL,BL ; nº sectores transferidos
- rwv_end: MOV AH,DS:[41h]
- OR AH,AH ; ¿error?
- JZ rwv_exit
- STC ; señalizar error
- rwv_exit: MOV r_al,AL ; nº sectores transferidos
- JMP main_exit
- read_wr_verify ENDP
-
- ; ------------ Función 5: Formatear pista.
-
- format_track PROC
- CMP DL,1
- JBE fmt_do
- MOV AH,1 ; función/parámetro incorrecto
- fmt_exit_err: MOV DS:[41h],AH ; código de error
- STC
- JMP main_exit
- fmt_do: MOV SI,90h
- PUSH DX
- XOR DH,DH
- ADD SI,DX ; [SI] -> estado físico unidad
- POP DX
- CMP BYTE PTR DS:[SI],0
- MOV AH,80h ; "unidad no preparada"
- JE fmt_exit_err ; indeterminado
- MOV DI,3Fh
- OR BYTE PTR DS:[DI],80h ; no esperar INT
- CALL motor_on ; arrancar motores
- CALL read_disk_chg ; leer línea de cambio de disco
- JNC fmt_posible ; no hay cambio de disco
- fmt_err: CALL end_io_access
- JMP fmt_exit_err ; error
- fmt_posible: CALL select_rate ; seleccionar la velocidad
- CALL send_specify ; enviar comando specify
- PUSH DS
- XOR SI,SI
- MOV DS,SI
- LDS SI,DWORD PTR DS:[78h] ; DS:SI -> INT 1Eh
- IFDEF XTDEBUG ; (se usó en las pruebas)
- MOV AL,r_AL ; [+] sectores por pista
- MOV [SI+4],AL ; [+]
- ELSE
- MOV AL,[SI+4] ; sectores por pista
- ENDIF
- POP DS
- XOR AH,AH
- MOV CL,4
- MUL CL ; 4 bytes para cada uno
- MOV CX,AX
- DEC CX ; un byte menos...
- CALL eval_dir_DMA ; ...cuenta para el DMA
- JC fmt_err ; cruza frontera de DMA
- MOV AH,4Ah ; modo DMA para escritura
- CALL set_dma ; preparar DMA
- MOV CX,r_cx ; restaurar CX
- CALL seek ; llevar el cabezal a la pista
- JNC fmt_continue ; no hay problemas
- fmt_err_res: MOV BX,42h
- MOV CX,7
- PUSH AX
- CALL get_results ; leer bytes de resultados
- POP AX
- JMP fmt_exit ; error
- fmt_continue: XSHL DH,2
- OR DH,DL ; DH = byte 1 del comando
- MOV DL,0CDh ; comando de formateo del FDC
- PUSH DS
- XOR SI,SI
- MOV DS,SI
- LDS SI,DWORD PTR DS:[78h] ; DS:SI -> INT 1Eh
- PUSH AX
- MOV AX,[SI+7] ; GAP formateo/byte de relleno
- MOV [BP],AX ; preservarlo
- POP AX
- MOV DI,[SI+3] ; bytes/sector, sectores/pista
- POP DS
- MOV SI,DX ; primeros bytes del comando
- MOV CH,6 ; comando de 6 bytes
- AND BYTE PTR DS:[3Eh],7Fh ; con espera de IRQ
- CALL exec_cmd
- JC fmt_err_res ; hay error
- MOV BX,42h
- MOV CX,7
- CALL get_results ; leer bytes de resultados
- JC fmt_exit
- CALL get_bios_err ; obtener código de error
- fmt_exit: MOV DS:[41h],AH ; código de error
- CALL end_io_access
- MOV AH,DS:[41h]
- OR AH,AH
- JZ fmt_end ; no hay error
- STC
- fmt_end: JMP main_exit
- format_track ENDP
-
- ; ------------ Función 8: Obtener parámetros de disco.
-
- get_drv_param PROC
- CMP DL,80h
- JB gdrv_do
- MOV AH,1 ; función/parámetro incorrecto
- MOV DS:[41h],AH ; código de error
- STC
- JMP main_exit
- gdrv_do: XOR DI,DI
- XOR SI,SI
- XOR DH,DH
- MOV AL,DS:[10h] ; hardware instalado
- AND AL,0C1h ; nº disqueteras (7-6) y bit
- MOV DI,2 ; que indica arrancable (0)
- CMP AL,41h ; ¿dos disqueteras? (DI=2)
- JE gdrv_ndisk_ok ; en efecto
- DEC DI
- CMP AL,1 ; ¿una disquetera? (DI=1)
- JE gdrv_ndisk_ok ; así es
- JMP gdrv_res_null ; no hay disqueteras
- gdrv_ndisk_ok: CMP DL,1
- JBE gdrv_a_or_b ; la disquetera es A: o B:
- JMP gdrv_half_res
- gdrv_a_or_b: CALL peek_cmos ; leer tipo de disqueteras
- OR DL,DL
- JNZ gdrv_sel
- MOV CL,4
- SHR AL,CL ; dejar disquetera en bits 0-3
- gdrv_sel: AND AL,0Fh
- JZ gdrv_media? ; no existe esa unidad
- CMP AL,5
- JA gdrv_media? ; es mayor de 2.88M
- XOR AH,AH
- MOV SI,AX
- MOV DH,AL
- MOV BX,90h
- ADD BL,DL ; [BX] -> estado físico unidad
- MOV AL,[BX]
- TEST AL,10h ; ¿densidad determinada?
- JNZ gdrv_calc_p ; en efecto
- CMP SI,1 ; ¿unidad de 360K?
- MOV AL,93h ; 360K en 360K, 250 Kbps
- JE gdrv_media_ok
- CMP SI,2 ; ¿unidad de 1.2M?
- MOV AL,2 ; "intentando 1.2M"
- JE gdrv_media_ok
- CMP SI,3 ; ¿unidad de 720K?
- MOV AL,97h ; 720K en 720K, 250 Kbps
- JE gdrv_media_ok
- CMP SI,4 ; ¿unidad de 1.44M?
- MOV AL,7 ; "intentando 1.44M"
- JE gdrv_media_ok
- MOV AL,0C7h ; 2.88M en 2.88M
- gdrv_media_ok: MOV [BX],AL
- JMP gdrv_calc_p ; medio físico asignado
- gdrv_media?: MOV BX,90h
- ADD BL,DL ; [BX] -> estado físico unidad
- MOV AL,[BX]
- TEST AL,10h ; ¿densidad determinada?
- JZ gdrv_eval ; no
- MOV AH,AL
- AND AL,0C0h ; aislar bits de velocidad
- CMP AL,80h ; ¿250 Kbps?
- MOV SI,2 ; 1.2M
- JNE gdrv_m144?
- TEST AH,4
- MOV SI,1 ; 360K
- JZ gdrv_calc_p
- MOV SI,4 ; 1.44M
- gdrv_m144?: TEST AH,7
- JZ gdrv_calc_p
- MOV SI,4 ; 1.44M
- gdrv_calc_p: MOV BX,DI
- MOV DI,SI
- DEC DI
- ADD DI,DI
- MOV AX,CS:tab_disksize[DI] ; AL sect/pista, AH pistas
- MOV r_dh,1 ; dos cabezales
- MOV DI,CS:tab_ptr_1e[DI] ; DI -> tabla parámetros
- PUSH CS
- POP ES ; ES:DI -> parámetros disco
- gdrv_set_res: MOV r_dl,BL ; número de unidades
- MOV r_ch,AH ; mayor número de cilindro
- MOV r_cl,AL ; mayor número de sector
- MOV r_bl,DH ; tipo de la unidad
- MOV r_bh,0
- MOV r_es,ES ; ES:DI para la salida
- MOV r_di,DI
- XOR AX,AX
- MOV DS:[41h],AH ; resultado correcto
- MOV r_al,AL
- JMP main_exit
- gdrv_res_null: XOR DI,DI ; devolver todo a 0
- gdrv_half_res: XOR DH,DH
- XOR AX,AX
- MOV ES,AX
- MOV r_dh,0
- MOV BX,DI
- XOR DI,DI
- JMP gdrv_set_res ; resultado trivial
- gdrv_eval: MOV BX,DI
- OR SI,SI
- JZ gdrv_res_null ; no existe la unidad
- CMP SI,3
- JBE gdrv_calc_p ; es de 5¼
- XOR SI,SI
- JMP gdrv_res_null
- get_drv_param ENDP
-
- ; ------------ Función 18h: Establecer densidad de formateo.
-
- set_media_fmt PROC
- CMP DL,1
- JBE setm_do
- MOV AH,1 ; función/parámetro incorrecto
- setm_exit_err: STC
- JMP main_exit
- setm_do: CALL get_drive_type ; obtener tipo disquetera en AL
- JZ setm_drv_ok
- setm_drv_unkn: MOV AH,0Ch ; tipo de unidad desconocido
- JMP setm_exit_err
- setm_drv_ok: XOR AH,AH
- MOV DI,AX ; tipo de unidad
- MOV DL,r_dl
- MOV BX,90h
- XOR DH,DH
- ADD BX,DX ; [BX] -> estado físico unidad
- CMP AL,1 ; ¿360K?
- JNE setm_not360
- MOV CX,r_cx ; restaurar CX
- CMP CX,2709h ; ¿40 pistas 9 sectores?
- LEA SI,t360in360
- JNZ setm_drv_unkn ; sólo se permite ese formato
- JMP setm_360in360
- setm_not360: CMP AL,3 ; ¿720K?
- JNE setm_not720
- MOV CX,r_cx ; restaurar CX
- CMP CX,4F09h ; ¿80 pistas 9 sectores?
- JNE setm_drv_unkn ; sólo se permite ese formato
- JMP setm_setm
- setm_not720: CMP AL,4 ; ¿1.44M?
- JE setm_1440
- CMP AL,2 ; ¿1.2M?
- JE setm_1200
- CMP AL,5 ; ¿2.88M?
- JNE setm_drv_unkn
- MOV CX,r_cx ; 2.88M: restaurar CX
- CMP CX,4F24h ; ¿80 pistas 36 sectores?
- JE setm_setm ; correcto
- CMP CX,4F12h ; ¿80 pistas 18 sectores?
- JE setm_setm ; correcto
- CMP CX,4F09h ; ¿80 pistas 9 sectores?
- JE setm_setm ; correcto
- JMP setm_drv_unkn ; permitir sólo esos formatos
- setm_1200: MOV CX,r_cx ; restaurar CX
- CMP CX,4F0Fh ; ¿80 pistas 15 sectores?
- JE setm_setm ; correcto
- CMP CX,2709h ; ¿80 pistas 9 sectores?
- JNE setm_drv_unkn ; permitir sólo esos formatos
- JMP setm_setm ; correcto
- setm_1440: MOV CX,r_cx ; restaurar CX
- CMP CX,4F12h ; ¿80 pistas 18 sectores?
- JE setm_setm ; correcto
- CMP CX,4F09h ; ¿80 pistas 9 sectores?
- JNE setm_drv_unkn ; permitir sólo esos formatos
- setm_setm: MOV CX,r_cx ; restaurar CX
- CMP CX,4F12h ; ¿80 pistas 18 sectores?
- MOV AL,17h ; su byte de medio físico
- LEA SI,t1440 ; es 1.44M
- MOV DH,0 ; 500 Kbps
- JZ setm_m_ok
- CMP CX,4F09h ; ¿80 pistas 9 sectores?
- MOV AL,97h ; su byte de medio físico
- LEA SI,t720 ; es 720K
- MOV DH,2 ; 250 Kbps
- JZ setm_m_ok
- CMP CX,4F0Fh ; ¿80 pistas 15 sectores?
- MOV AL,15h ; su byte de medio físico
- LEA SI,t1200 ; es 1.2M
- MOV DH,0 ; 500 Kbps
- JZ setm_m_ok
- CMP CX,4F24h ; ¿80 pistas 36 sectores?
- MOV AL,0D7h ; su byte de medio físico
- LEA SI,t2880 ; es 2.88M
- MOV DH,3 ; 1 Mbps
- JZ setm_m_ok
- MOV AL,74h ; byte medio físico 360K en 1.2
- LEA SI,t360en1200 ; es 360K en 1.2M
- MOV DH,1 ; 300 Kbps
- setm_m_ok: MOV [BX],AL ; establecer medio físico
- PUSH DX
- CALL set_rate ; velocidad de transferencia DH
- POP DX
- MOV AL,[BX]
- AND AL,0C0h
- AND BYTE PTR DS:[8Bh],3Fh ; borrar bits de velocidad
- OR BYTE PTR DS:[8Bh],AL ; nueva velocidad
- MOV r_di,SI
- MOV r_es,CS ; retornar tabla parámetros
- MOV BYTE PTR DS:[41h],0 ; no hay error
- XOR AH,AH
- JMP main_exit
- setm_360in360: MOV DH,2 ; 250 Kbps
- MOV AL,93h ; 360K en 360K
- JMP setm_m_ok
- set_media_fmt ENDP
-
- ; ------------ Recalibrar.
-
- recalibrate PROC
- PUSH SI
- PUSH CX
- PUSH DX
- MOV DH,DL
- MOV DL,7 ; comando "recalibrate"
- MOV SI,DX
- MOV CH,2 ; comando de 2 bytes
- AND BYTE PTR DS:[3Eh],7Fh ; con espera de IRQ
- CALL exec_cmd
- JC recal_end ; fallo
- MOV SI,8 ; "leer estado interrupciones"
- MOV CH,1 ; comando de 1 byte
- OR BYTE PTR DS:[3Eh],80h ; sin espera de IRQ
- CALL exec_cmd
- JC recal_end ; fallo
- MOV BX,42h
- MOV CX,2 ; 2 bytes de resultado
- CALL get_results ; almacenar resultado
- JC recal_end ; fallo
- MOV BX,42h
- MOV AH,40h
- MOV DL,[BX] ; ST0
- AND DL,60h
- CMP DL,60h ; ¿terminación anormal y
- STC ; seek-end?
- JE recal_end ; fallo
- POP DX
- PUSH DX
- XOR DH,DH
- MOV BX,94H
- ADD BX,DX
- MOV BYTE PTR DS:[BX],0 ; cilindro en curso = 0
- MOV CL,DL
- MOV DL,1
- SHL DL,CL
- OR DS:[3Eh],DL ; unidad recalibrada
- IFNDEF XT
- MOV CX,43h
- CALL wait_time ; retardo de 1 ms
- ELSE
- MOV CX,1
- CALL retardo ; retardo de 1 ms
- ENDIF
- XOR AH,AH
- recal_end: MOV DS:[41h],AH ; código de error / acierto
- POP DX
- POP CX
- POP SI
- RET
- recalibrate ENDP
-
- ; ------------ Llevar el cabezal al cilindro adecuado.
-
- seek PROC
- PUSH BX
- PUSH CX
- MOV AH,DS:[3Eh] ; estado de recalibración
- MOV CL,DL
- INC CL
- SHR AH,CL
- JC seek_only
- CALL recalibrate ; hay que recalibrar
- JNC seek_only
- CALL recalibrate ; segundo intento
- JNC seek_only
- JMP seek_exit
- seek_only: MOV BX,94H
- XOR DH,DH
- ADD BX,DX ; [BX] -> cilindro actual
- MOV SI,90h
- ADD SI,DX ; [SI] -> estado físico unidad
- MOV DL,CH
- TEST BYTE PTR DS:[SI],20h ; ¿hacer double stepping?
- JZ seek_cil_ok1
- ADD DL,DL ; sí: cilindro=cilindro*2
- seek_cil_ok1: CMP [BX],DL ; ¿ya estamos en ese cilindro?
- MOV DX,r_dx
- JNE seek_do ; aún no
- CMP BYTE PTR DS:[41h],40h ; ¿hubo "seek error"?
- JE seek_do
- XOR AH,AH ; no, seek innecesario
- JMP seek_exit
- seek_do: XSHL DH,2
- OR DH,DL ; byte 1 del comando seek
- MOV DL,0FH ; orden seek
- MOV SI,DX
- MOV CL,CH ; cilindro
- MOV DX,r_dx ; unidad / cabezal
- MOV BX,90h
- XOR DH,DH
- ADD BX,DX ; [BX] -> estado físico
- TEST BYTE PTR DS:[BX],20h ; ¿hacer double stepping?
- JZ seek_cil_ok2 ; no
- ADD CL,CL ; sí: cilindro=cilindro*2
- seek_cil_ok2: MOV DI,CX
- MOV CH,3 ; comando de 3 bytes
- AND BYTE PTR DS:[3Eh],7Fh ; hay que esperar IRQ
- CALL exec_cmd
- JNC seek_ok ; seek correcto
- JMP seek_result
- seek_ok: MOV SI,8 ; "leer estado interrupciones"
- MOV CH,1 ; comando de 1 byte
- OR BYTE PTR DS:[3Eh],80h ; no hay que esperar IRQ
- CALL exec_cmd
- JC seek_result ; fallo
- MOV BX,42h
- MOV CX,2
- CALL get_results ; leer bytes de resultados
- JC seek_result
- MOV BX,42h
- MOV AH,40h ; "seek error"
- MOV DL,[BX] ; ST0
- AND DL,60h
- CMP DL,60h ; comprobarlo
- STC
- JE seek_result ; terminación brusca
- MOV DX,r_dx ; restaurar DX
- POP CX
- PUSH CX ; restaurar CX
- MOV SI,94H
- XOR DH,DH
- ADD SI,DX
- MOV [SI],CH ; actualizar cilindro actual
- MOV BX,90h
- ADD BX,DX ; [BX] -> estado físico unidad
- MOV BL,[BX]
- TEST BL,20h ; ¿double stepping?
- JZ seek_cil_ok3
- ADD [SI],CH ; pues cilindro*2
- seek_cil_ok3: PUSH DS
- XOR SI,SI
- MOV DS,SI
- LDS SI,DWORD PTR DS:[78h] ; DS:SI -> INT 1Eh
- MOV AL,[SI+9] ; tiempo estabilización cabezal
- POP DS
- TEST BYTE PTR DS:[3Fh],80h ; ¿operación en curso?
- JZ seek_wait ; es lectura o verificación
- OR AL,AL
- JNZ seek_wait ; escritura, cte != 0
- CMP BL,17h
- MOV AL,0Fh
- JE seek_wait ; 15 ms excepto para 360K
- AND BL,7
- MOV AL,14h
- JZ seek_wait ; 20 ms para unidades de 360K
- CMP BL,3
- JE seek_wait ; 20 ms para unidades de 360K
- MOV AL,0Fh ; 15 ms para demás unidades
- seek_wait: OR AL,AL
- JZ seek_wait_end
- IFNDEF XT
- MOV CX,43h
- CALL wait_time ; esperar 1 ms...
- ELSE
- MOV CX,1
- CALL retardo ; retardo de 1 ms
- ENDIF
- DEC AL
- JMP seek_wait ; ...durante AL veces
- seek_wait_end: XOR AH,AH
- seek_result: MOV DS:[41h],AH ; resultado
- seek_exit: MOV DX,r_dx ; restaurar DX
- POP CX
- POP BX
- RET
- seek ENDP
-
- ; ------------ Ejecutar operación de E/S a través del FDC.
-
- perform_io PROC
- CALL seek
- JNC p_io
- p_io_dsk_err: MOV AL,0 ; fallo
- PUSH AX
- MOV BX,42h
- MOV CX,7
- CALL get_results ; leer bytes de resultados
- POP AX
- JMP p_io_exit
- p_io: PUSH DS ; preparar bytes comando R/W
- XOR SI,SI
- MOV DS,SI
- LDS SI,DWORD PTR DS:[78h] ; DS:SI -> INT 1Eh
- MOV AX,[SI+2]
- AND AX,0FF00h ; AH = bytes por sector
- MOV AL,CL ; AL = primer sector
- MOV [BP],AX
- MOV BX,[SI+4] ; BL=sectores/pista, BH=GAP R/W
- MOV CL,[SI+6] ; CL=longitud de sector (tam=0)
- POP DS
- MOV SI,90h
- XOR DH,DH
- ADD SI,DX ; nº sector/tamaño (bytes 4-5)
- MOV DL,[SI] ; estado físico de la unidad
- AND DL,7
- MOV DH,1Bh ; GAP R/W para 1.2M/1.44M/2.88M
- CMP DL,5
- JE p_io_gap_ok ; 1.2M en 1.2M
- CMP BYTE PTR DS:[SI],17h
- JE p_io_gap_ok ; 1.44M
- CMP BYTE PTR DS:[SI],0D7h
- JE p_io_gap_ok ; 2.88M
- MOV DH,23h ; GAP R/W para 360K en 1.2M
- CMP DL,4
- JE p_io_gap_ok ; 360K en 1.2M
- MOV DH,2Ah ; GAP R/W para demás casos
- p_io_gap_ok: MOV BH,DH ; BX=numsect/GAP (bytes 6-7)
- MOV DX,r_dx ; restaurar DX
- PUSH CX
- MOV CL,CH ; cilindro
- MOV CH,DH ; cabezal
- MOV DI,CX ; cabezal/cilindro (bytes 2-3)
- XSHL DH,2
- OR DH,DL ; byte 1 de comando FDC
- MOV DL,0E6h ; comando leer datos
- MOV AX,r_ax ; orden
- CMP AH,3 ; ¿write?
- JNE p_io_orden_ok
- MOV DL,0C5h ; comando escribir datos
- p_io_orden_ok: MOV SI,DX ; (bytes 0-1 de la orden)
- POP CX
- MOV CH,9
- AND BYTE PTR DS:[3Eh],7Fh ; esperar interrupción
- CALL exec_cmd
- JNC p_io_dsk_ok
- JMP p_io_dsk_err ; fallo
- p_io_dsk_ok: MOV BX,42h
- MOV CX,7
- CALL get_results ; leer bytes de resultados
- JNC p_io_res_ok
- MOV AL,0
- JMP p_io_exit ; fallo: respetar código error
- p_io_res_ok: CALL get_bios_err
- p_io_exit: MOV DS:[41h],AH
- MOV DX,r_dx ; restaurar registros
- MOV BX,r_bx
- MOV CX,r_cx
- JMP io_performed ; continuar operación E/S
- perform_io ENDP
-
- ; ------------ Arrancar motor si no lo está.
-
- motor_on PROC
- PUSH DX
- PUSH CX
- CLI ; * evitar reentrada
- MOV BYTE PTR DS:[40h],0FFh ; evitar detención motor
- AND BYTE PTR DS:[3Fh],0CFh ; a 0 bits de disquetera
- MOV CH,DL
- XSHL DL,4
- OR DS:[3Fh],DL ; nueva disquetera seleccionada
- MOV CL,CH
- MOV DL,DS:[3Fh] ; estado de motores
- INC CL
- SHR DL,CL
- JC motor_is_on ; motor ya en marcha
- MOV DL,1
- DEC CL
- SHL DL,CL
- OR DS:[3Fh],DL ; señalizar que está en marcha
- STI ; * fin de la fase crítica
- MOV AL,DS:[3Fh] ; estado de motores
- XROR AL,4
- OR AL,0CH ; no resetear, modo DMA
- MOV DX,3F2h
- OUT DX,AL ; registro salida digital
- MOV AX,90FDh
- INT 15h ; permitir multitarea
- JC motor_on_end
- MOV AH,DS:[3Fh]
- PUSH DS
- PUSH SI
- XOR SI,SI
- MOV DS,SI
- LDS SI,DWORD PTR DS:[78h] ; DS:SI -> INT 1Eh
- MOV AL,[SI+0Ah]
- POP SI ; AL = tiempo aceleración motor
- POP DS ; en octavos de segundo
- SHL AH,1
- JNC motor_on_rv ; operación read/verify
- CMP AL,8
- JAE motor_on_wait
- MOV AL,8
- JMP motor_on_wait ; escritura: al menos 1 segundo
- motor_on_rv: CMP AL,5
- JAE motor_on_wait
- MOV AL,5 ; read/verify: al menos 625 ms
- motor_on_wait:IFNDEF XT
- MOV CX,208EH
- CALL wait_time ; retardo de unos 125 ms
- ELSE
- MOV CX,125
- CALL retardo ; retardo de unos 125 ms
- ENDIF
- DEC AL
- JNZ motor_on_wait ; completar retardo
- JMP motor_on_end
- motor_is_on: STI
- MOV AL,DS:[3Fh] ; estado de motores
- XROR AL,4
- OR AL,0CH ; no resetear, modo DMA
- MOV DX,3F2h
- OUT DX,AL ; seleccionar unidad
- motor_on_end: POP CX
- POP DX
- RET
- motor_on ENDP
-
- ; ------------ Asignar cuenta para detención motor y devolver en BL
- ; y AL el próximo número de sector a transferir.
-
- end_io_access PROC
- PUSH AX
- PUSH DS
- XOR BX,BX
- MOV DS,BX
- LDS BX,DWORD PTR DS:[78h] ; DS:BX -> INT 1Eh
- MOV AH,[BX+2] ; tics hasta detención motor
- MOV AL,[BX+4]
- INC AL ; sectores/pista + 1
- POP DS
- MOV BX,42h
- CMP CH,[BX+3] ; ¿mismo cilindro resultante?
- JNE end_io_exit
- CMP DH,[BX+4] ; ¿mismo cabezal resultante?
- JNE end_io_exit
- MOV AL,[BX+5] ; número de sector resultante
- end_io_exit: MOV DS:[40h],AH ; tiempo para detención motor
- MOV BL,AL ; último nº sector transferido
- POP AX
- RET
- end_io_access ENDP
-
- ; ------------ Leer la línea de cambio de disco y bajarla si está
- ; activa.
-
- read_disk_chg PROC
- PUSH CX
- CALL get_drive_type ; obtener tipo disquetera en AL
- MOV AH,0
- JNZ fallo_cmos
- CMP AL,3 ; [+] Evitar test en 720K:
- JE rdchg_set_cod ; [+] Bug en BIOS AMI original?
- DEC AL
- JZ rdchg_set_cod ; evitar test en 360K
- fallo_cmos: MOV AL,[SI] ; estado físico de la unidad
- AND AL,7
- JZ rdchg_set_cod ; evitar test en 360K
- CMP AL,3
- JE rdchg_set_cod ; evitar test en 360K
- MOV DX,3F7h ; registro de entrada digital
- IN AL,DX ; leer línea de cambio de disco
- SHL AL,1
- JNC rdchg_exit ; no hay cambio de disco
- AND BYTE PTR DS:[SI],0EFH ; medio no determinado
- CALL full_init ; inicialización plena
- JC rdchg_exit ; fallo
- MOV DX,r_dx ; restaurar DX
- MOV CH,1
- CALL seek ; cabezal a cilindro 1
- JC rdchg_exit
- MOV CH,0
- CALL seek ; cabezal a cilindro 0
- JC rdchg_exit
- MOV AH,6 ; error "disk changed"
- MOV DX,3F7h
- IN AL,DX ; leer línea de cambio de disco
- SHL AL,1
- JNC rdchg_set_cod ; se ha podido bajar
- MOV AH,80h ; no se pudo: no hay disquete
- rdchg_set_cod: OR AH,AH
- JZ rdchg_exit
- STC
- rdchg_exit: MOV DX,r_dx ; restaurar DX
- POP CX
- RET
- read_disk_chg ENDP
-
- ; ------------ Programar el DMA para efectuar la E/S.
-
- set_dma PROC
- PUSH AX
- PUSH DX
- CLI
- MOV AL,AH
- OUT 0CH,AL ; clear first/last flip-flop
- JMP SHORT $+2 ; retardo para E/S
- JMP SHORT $+2
- OUT 0BH,AL ; registro de modo del DMA
- JMP SHORT $+2
- JMP SHORT $+2
- MOV AL,CL
- OUT 5,AL
- JMP SHORT $+2
- JMP SHORT $+2
- MOV AL,CH
- OUT 5,AL ; enviada cuenta de bytes
- JMP SHORT $+2
- JMP SHORT $+2
- MOV AL,BL
- OUT 4,AL
- JMP SHORT $+2
- JMP SHORT $+2
- MOV AL,BH
- OUT 4,AL ; enviada dirección base
- JMP SHORT $+2
- JMP SHORT $+2
- MOV AX,ES
- OUT 81H,AL ; registro de página canal 2
- JMP SHORT $+2
- JMP SHORT $+2
- MOV AL,2
- OUT 0AH,AL ; habilitar canal 2 del DMA
- STI
- POP DX
- POP AX
- RET
- set_dma ENDP
-
- ; ------------ Calcular parámetros para programar el DMA.
-
- eval_dir_DMA PROC
- PUSH CX
- XOR AX,AX
- MOV CX,ES ; segmento ES
- SHL CX,1 ; desplazar...
- RCL AL,1
- SHL CX,1
- RCL AL,1
- SHL CX,1
- RCL AL,1
- SHL CX,1
- RCL AL,1 ; ... AL:CX >> 4
- MOV BX,r_bx ; offset BX
- ADD BX,CX
- ADC AX,0 ; AX:BX dirección física 20 bit
- MOV ES,AX ; página de DMA
- POP CX
- MOV AX,CX
- ADD AX,BX
- JNC eval_dma_ret ; no cruza frontera de 64k
- MOV AH,9 ; "DMA across 64k boundary"
- eval_dma_ret: RET
- eval_dir_DMA ENDP
-
- ; ------------ Enviar comando completo al FDC de CH bytes, contenido
- ; en SI, DI, [BP], BX y CL (parte baja - alta).
-
- send_full_cmd PROC
- MOV AX,SI
- MOV AH,AL
- CALL fdc_write ; enviar SI-L
- DEC CH
- JBE send_full_ret ; acabado (ZF=1) ó error (CF=1)
- MOV AX,SI
- CALL fdc_write ; enviar SI-H
- DEC CH
- JBE send_full_ret
- MOV AX,DI
- MOV AH,AL
- CALL fdc_write ; enviar DI-L
- DEC CH
- JBE send_full_ret
- MOV AX,DI
- CALL fdc_write ; enviar DI-H
- DEC CH
- JBE send_full_ret
- MOV AX,[BP]
- MOV AH,AL
- CALL fdc_write ; enviar [BP]-L
- DEC CH
- JBE send_full_ret
- MOV AX,[BP]
- CALL fdc_write ; enviar [BP]-H
- DEC CH
- JBE send_full_ret
- MOV AH,BL
- CALL fdc_write ; enviar BL
- DEC CH
- JBE send_full_ret
- MOV AH,BH
- CALL fdc_write ; enviar BH
- DEC CH
- JBE send_full_ret
- MOV AH,CL
- CALL fdc_write ; enviar CL
- send_full_ret: RET
- send_full_cmd ENDP
-
- ; ------------ Enviar comando al FDC con/sin espera de interrupción.
-
- exec_cmd PROC
- TEST BYTE PTR DS:[3Eh],80h ; ¿hay que esperar IRQ?
- JZ exec_cmd_irq ; sí
- AND BYTE PTR DS:[3Eh],7Fh ; no: devolver a 0 bit IRQ
- CALL send_full_cmd ; enviar comando
- RET
- exec_cmd_irq: CALL send_full_cmd ; enviar comando
- JC exec_cmd_ret
- MOV AX,9001h
- INT 15h ; permitir multitarea
- STI
- JC exec_cmd_err
- CALL wait_int ; esperar IRQ
- JNC exec_cmd_ok
- exec_cmd_err: MOV AH,80h ; "not ready" (AH=80h)
- exec_cmd_ret: RET
- exec_cmd_ok: AND BYTE PTR DS:[3Eh],7Fh ; bit IRQ listo para otra
- XOR AH,AH ; éxito
- RET
- exec_cmd ENDP
-
- ; ------------ Enviar byte al FDC.
-
- IFNDEF XT
-
- fdc_write PROC
- PUSH CX
- PUSH DX
- MOV CX,2
- CALL wait_time ; esperar 15-30 µs
- MOV DX,3F4h ; registro de estado
- PUSH AX
- MOV AH,40h
- XOR CX,CX
- CALL wait0 ; esperar FDC listo para OUT
- JC fdc_wr_fail
- MOV AH,80h
- XOR CX,CX
- CALL wait1
- JC fdc_wr_fail ; error
- POP AX
- MOV DX,3F5h ; registro de datos
- MOV AL,AH
- OUT DX,AL ; escribir el byte
- JMP fdc_wr_ret
- fdc_wr_fail: POP AX
- MOV AH,80h ; error "not ready"
- fdc_wr_ret: POP DX
- POP CX
- RET
- fdc_write ENDP
-
- ELSE
-
- fdc_write PROC
- XPUSH <CX, DX, AX>
- MOV DX,3F4h ; registro de estado del FDC
- XOR CX,CX ; evitar cuelgue total si falla
- espera_wr: IN AL,DX ; leer registro de estado
- TEST AL,80h ; ¿bit 7 inactivo?
- LOOPZ espera_wr ; así es: el FDC está ocupado
- JCXZ fdc_wr_nok
- POP AX
- PUSH AX
- INC DX ; apuntar al registro de datos
- MOV AL,AH
- OUT DX,AL ; enviar byte al FDC
- XPOP <AX, DX, CX>
- CLC
- RET
- fdc_wr_nok: POP AX
- MOV AH,80h ; timeout
- XPOP <DX, CX>
- STC
- RET
- fdc_write ENDP
-
- ENDIF
-
- ; ------------ Leer del FDC CX bytes de resultado en [BX++].
-
- get_results PROC
- PUSH DX
- get_one_byte: PUSH CX
- CALL fdc_read
- POP CX
- JC get_res_ret ; no hay más bytes que leer
- MOV [BX],AL
- INC BX
- LOOP get_one_byte ; leer todos los bytes
- IFNDEF XT
- MOV CX,4
- CALL wait_time ; esperar 45-60 µs
- ELSE
- CALL retardo53 ; retardo de 53 ms
- ENDIF
- MOV DX,3F4h
- IN AL,DX ; leer registro de estado
- TEST AL,10h
- JZ get_res_ok ; el FDC no está ocupado
- MOV AH,20h
- STC ; lo estaba: "bad NEC"
- JMP get_res_ret
- get_res_ok: XOR AH,AH ; operación correcta
- get_res_ret: POP DX
- RET
- get_results ENDP
-
- ; ------------ Leer byte del FDC.
-
- IFNDEF XT
-
- fdc_read PROC
- PUSH DX
- MOV CX,3
- CALL wait_time ; esperar 30-45 µs
- MOV DX,3F4h ; registro de estado
- MOV AH,80h
- XOR CX,CX
- CALL wait1 ; esperar FDC listo para E/S
- MOV AH,80h
- JC fdc_read_end ; error "not ready" (AH=80h)
- IN AL,DX
- TEST AL,40h ; ¿el FDC quiere dar un byte?
- JNZ fdc_read_ok
- MOV AH,20H ; no: error "bad NEC" (AH=20h)
- STC
- JMP fdc_read_end
- fdc_read_ok: JMP SHORT $+2 ; retardo para E/S
- JMP SHORT $+2
- MOV DX,3F5h ; registro de datos
- IN AL,DX ; leer el byte
- fdc_read_end: POP DX
- RET
- fdc_read ENDP
-
- ELSE
-
- fdc_read PROC
- XPUSH <CX, DX>
- MOV DX,3F4h ; registro de estado del FDC
- XOR CX,CX ; evitar cuelgue total si falla
- espera_rd: IN AL,DX ; leer registro de estado
- TEST AL,80h ; ¿bit 7 inactivo?
- LOOPZ espera_rd ; así es: el FDC está ocupado
- JCXZ fdc_rd_nok
- INC DX ; apuntar al registro de datos
- IN AL,DX ; leer byte del FDC
- CLC
- XPOP <DX, CX>
- RET
- fdc_rd_nok: MOV AH,80h ; timeout
- STC
- XPOP <DX, CX>
- RET
- fdc_read ENDP
-
- ENDIF
-
- ; ------------ Obtener código de error de la BIOS.
-
- get_bios_err PROC
- MOV BX,42h ; área de resultados del FDC
- MOV BX,[BX]
- TEST BL,0C0h ; ¿que tal ST0?
- MOV AH,0
- JZ bios_err_det ; ¡perfecto!
- TEST BL,40h ; ¿terminación brusca/anormal?
- MOV AH,20H ; "bad NEC"
- JZ bios_err_det
- TEST BH,1 ; ¿falta marca de direcciones?
- MOV AH,2 ; "address mark not found"
- JNZ bios_err_det
- TEST BH,2 ; ¿protegido contra escritura?
- MOV AH,3 ; "write-protect error"
- JNZ bios_err_det
- TEST BH,4 ; ¿sector no encontrado?
- MOV AH,4 ; "sector not found"
- JNZ bios_err_det
- TEST BH,10H ; ¿DMA no atendido a tiempo?
- MOV AH,8 ; "DMA overrun"
- JNZ bios_err_det
- TEST BH,20H ; ¿falla el CRC?
- MOV AH,10H ; "CRC error"
- JNZ bios_err_det
- TEST BH,80h ; ¿acceso fuera de la pista?
- MOV AH,4 ; "sector not found"
- JNZ bios_err_det
- MOV AH,20H ; otro error: "bad NEC"
- bios_err_det: RET
- get_bios_err ENDP
-
- ; ------------ Reinicializar la controladora de disquetes.
-
- init_fdc PROC
- CALL reset_disk ; resetear FDC
- JC init_fin ; fallo al resetear
- MOV DX,3F4h ; registro de estado del FDC
- IN AL,DX
- TEST AL,80h
- JZ init_otravez ; el FDC no está listo
- TEST AL,40h
- JZ init_bien ; el FDC espera datos de la CPU
- init_otravez: CALL reset_disk ; otro intento más
- MOV DX,3F4h
- IN AL,DX
- TEST AL,80h
- JZ init_mal ; nada, que no tira
- TEST AL,40h
- JZ init_bien ; bueno, ya despierta
- init_mal: MOV AH,20h ; fallo de la controladora
- STC
- JMP init_fin
- init_bien: MOV AH,8 ; "leer estado interrupciones"
- CALL fdc_write ; enviar comando
- JC init_fin ; fallo
- CALL fdc_read ; leer ST0
- JC init_fin ; fallo
- MOV DS:[42h],AL ; guardar ST0
- PUSH AX
- CALL fdc_read ; leer cilindro actual
- MOV DS:[42h+1],AL ; guardarlo
- POP CX
- JC init_fin ; fallo
- AND CL,0C0h
- CMP CL,0C0h ; ¿terminación anormal?
- JNE init_mal ; no es terminación anormal
- XOR AH,AH ; ok: el FDC detecta el fallo
- init_fin: JMP fdc_init
- init_fdc ENDP
-
- ; ------------ Resetear el FDC.
-
- reset_disk PROC
- CLI
- AND BYTE PTR DS:[3Fh],7Fh ; operación R/V
- AND BYTE PTR DS:[3Eh],7Fh ; borrar bit IRQ
- MOV AL,DS:[3Fh]
- XROL AL,4 ; bits 7-4: motores
- AND AL,0FBH ; bits 3-0: unidad
- OR AL,8 ; interrupciones ON + reset
- MOV DX,3F2h
- OUT DX,AL ; hacer reset
- IFNDEF XT
- MOV CX,3
- CALL wait_time ; retardo de 30-45µs
- ELSE
- CALL retardo53 ; pequeño retardo
- ENDIF
- OR AL,0CH
- OUT DX,AL ; fin del reset
- MOV AX,9001h
- INT 15h ; facilitar multitarea
- STI
- JC fin_wait ; error
- CALL wait_int ; esperar interrupción de disco
- fin_wait: MOV AH,80h ; "unidad no preparada"
- JC exit_reset ; hay error
- AND BYTE PTR DS:[3Eh],7Fh ; borrar bit IRQ
- XOR AH,AH ; no hay error
- exit_reset: RET
- reset_disk ENDP
-
- ; ------------ Enviar comando specify obtenido de INT 1Eh al FDC.
-
- send_specify PROC
- PUSH DS
- XOR BX,BX
- MOV DS,BX
- LDS BX,DWORD PTR DS:[78h] ; DS:BX -> INT 1Eh
- MOV AL,3 ; comando specify del FDC
- MOV AH,[BX] ; byte 0 del comando specify
- MOV SI,AX
- MOV AL,[BX+1] ; byte 1 del comando specify
- MOV DI,AX
- MOV CH,3 ; orden de 3 bytes (SI, DI-L)
- POP DS
- OR BYTE PTR DS:[3Eh],80h ; no esperar IRQ
- CALL exec_cmd ; mandar specify al FDC
- JMP specify_sent
- send_specify ENDP
-
- ; ------------ Esperar una interrupción de disco durante 2 segundos.
-
- IFNDEF XT
-
- wait_int PROC
- MOV BX,3Eh ; variable con flag de INT
- XOR CX,CX
- CALL wait_event ; esperar IRQ durante 1 segundo
- JNC wait_int_ret
- XOR CX,CX
- CALL wait_event ; esperar otro segundo más
- wait_int_ret: RET
- wait_int ENDP
-
- ELSE
-
- wait_int PROC
- MOV BX,3Eh ; variable con flag de INT
- MOV CX,37
- CALL wait_event ; esperar IRQ durante 2 seg.
- RET
- wait_int ENDP
-
- ENDIF
-
- ; ------------ Devolver en AL el tipo de la unidad DL.
-
- get_drive_type PROC
- CALL peek_cmos ; leer tipo de disqueteras
- OR DL,DL
- JNZ gdt_unidad_ok
- XSHR AL,4 ; unidad A:
- gdt_unidad_ok: AND AL,0Fh
- CMP SP,SP ; ZF=1 -> resultado correcto
- RET
- get_drive_type ENDP
-
- ; ------------ Determinar la densidad del disquete.
-
- detect_media PROC
- PUSH DX
- PUSH CX
- PUSH BX
- MOV BL,r_dl
- XOR BH,BH
- MOV DL,BL
- CALL get_drive_type ; obtener tipo disquetera en AL
- MOV AH,0
- JZ dm_fast ; ha sido posible obtenerlo
- JMP dm_slow ; usar procedimiento lento
- dm_fast: MOV BYTE PTR DS:[BX+90h],0 ; estado físico unidad
- DEC AX
- JNZ dm_es_1200K?
- MOV AL,93h ; 360K: 360K en 360K, 250 Kbps
- dm_try: PUSH AX
- MOV DH,AL
- AND DH,0C0h
- XSHR DH,6
- CALL set_rate ; velocidad de transferencia DH
- POP AX
- dm_result: MOV DS:[BX+90h],AL ; estado físico...
- TEST AL,10h ; ...¿determinado?
- JZ dm_fails ; aún no
- XOR AH,AH
- JMP dm_exit ; sí: resultado correcto
- NOP
- dm_es_1200K?: DEC AX
- JNZ dm_es_720K?
- MOV AL,0
- CALL read_ids ; 1.2M: 500 kbps
- MOV AL,15h ; indicar 1.2M en 1.2M
- JNC dm_result ; sí funciona
- MOV AL,40h
- MOV BYTE PTR DS:[BX+90h],2
- CALL read_ids ; probar 300 Kbps
- MOV AL,74h ; indicar 360K en 1.2M
- JNC dm_result ; sí funciona
- MOV AL,2 ; indicar "¿1.2M en 1.2M?"
- JMP dm_result
- dm_es_720K?: DEC AX
- JNZ dm_es_1440K?
- MOV AL,97h ; 720K: 250 Kbps
- JMP dm_try ; a probar suerte
- dm_es_1440K?: DEC AX
- JNZ dm_es_2880K
- MOV AL,0
- CALL read_ids ; 1.44M: 500 Kbps
- MOV AL,17h ; indicar 1.44M
- JNC dm_result ; sí funciona
- MOV AL,80h
- CALL read_ids ; probar a 250 Kbps
- MOV AL,97h ; indicar 720K
- JNC dm_result ; sí funciona
- MOV AL,7 ; indicar "¿1.44M?"
- JMP dm_result
- dm_es_2880K: MOV AL,0C0h
- CALL read_ids ; 2.88M: 1 Mbps
- MOV AL,0D7h ; indicar 2.88M en 2.88M
- JNC dm_result ; sí funciona
- MOV AL,0
- CALL read_ids ; probar 500 Kbps
- MOV AL,17h ; indicar 1.44M
- JNC dm_result ; sí funciona
- MOV AL,80h
- CALL read_ids ; probar 250 Kbps
- MOV AL,97h ; indicar 720K
- JNC dm_result ; sí funciona
- MOV AL,0C7h ; indicar "¿2.88M en 2.88M?"
- JMP dm_result
- dm_fails: STC ; condición de error
- dm_exit: MOV DS:[41h],AH ; código de error
- POP BX
- POP CX
- POP DX
- RET
- dm_slow: MOV AL,0
- CALL read_ids ; probar 500 Kbps
- MOV AL,15h ; indicar 1.2M en 1.2M
- JNC dm_slow_ok ; sí funciona
- MOV AL,40h
- MOV BYTE PTR DS:[BX+90h],2
- CALL read_ids ; probar 300 Kbps
- MOV AL,74h ; indicar 360K en 1.2M
- JNC dm_slow_ok ; sí funciona
- MOV AL,80h
- CALL read_ids ; probar 250 Kbps
- MOV AL,97h ; indicar 720K ó 360K en 360K
- JNC dm_slow_ok ; sí funciona
- MOV AL,0C0h
- CALL read_ids ; probar 1 Mbps
- MOV AL,0D7h ; indicar 2.88M en 2.88M
- JC dm_fails ; no funciona
- dm_slow_ok: JMP dm_result
- detect_media ENDP
-
- ; ------------ Efectuar una lectura de ID's a velocidad AL (bits 6-7).
-
- read_ids PROC
- PUSH BX
- PUSHF
- CLI
- MOV BYTE PTR DS:[40h],0FFh ; evitar detención motor
- POPF
- XSHR AL,6 ; colocar bits de velocidad
- MOV DH,AL
- CALL set_rate ; velocidad de transferencia DH
- MOV DL,r_dl
- CALL recalibrate ; recalibrar
- JNC read_id_try
- CALL recalibrate ; segundo intento
- JC read_id_err
- read_id_try: MOV CX,3 ; 3 intentos
- read_id_retry: PUSH CX
- MOV DH,DL ; en el cabezal 0 de la unidad
- MOV DL,4Ah ; comando de leer ID's
- MOV SI,DX
- MOV DL,DH
- MOV CH,2 ; comando de 2 bytes
- AND BYTE PTR DS:[3Eh],7Fh ; esperar interrupción
- CALL exec_cmd
- JC read_id_fails ; fallo
- MOV BX,42h
- MOV CX,7
- CALL get_results ; leer bytes de resultados
- JC read_id_fails
- CALL get_bios_err ; obtener código de error
- POP CX
- OR AH,AH
- JZ read_id_ret ; ya no hay fallo
- LOOP read_id_retry ; reintentar
- JMP read_id_err ; mala suerte
- read_id_fails: POP CX
- read_id_err: STC
- read_id_ret: POP BX
- RET
- read_ids ENDP
-
- ; ------------ Seleccionar la velocidad de transferencia adecuada.
-
- select_rate PROC
- PUSH SI
- MOV SI,90h
- XOR DH,DH
- ADD SI,DX ; [SI] -> estado físico unidad
- MOV DH,[SI] ; estado físico nueva unidad
- MOV DL,DS:[8Bh] ; control del medio físico
- AND DX,0C0C0h ; aislar bits de velocidad
- CMP DL,DH ; ¿velocidad ya seleccionada?
- JE selected_rate
- AND BYTE PTR DS:[8Bh],3Fh ; no: borrar la anterior
- OR DS:[8Bh],DH ; indicar la nueva
- AND DH,0C0h
- XROL DH,2
- CALL set_rate ; nueva velocidad transferencia
- selected_rate: POP SI
- MOV DX,r_dx ; restaurar DX
- RET
- select_rate ENDP
-
- ; ------------ Establecer la velocidad de transferencia DH.
-
- set_rate PROC
- PUSH AX
- MOV AL,DH
- MOV DX,3F7h ; registro de control del disquete
- OUT DX,AL ; seleccionar velocidad
- POP AX
- RET
- set_rate ENDP
-
- ; ------------ Esperar que alguno de los bits a 1 de AH en el
- ; puerto DX se pongan a 0 en no más de CX 15.09 µs.
-
- IFNDEF XT
-
- wait0 PROC
- PUSH AX
- wait0_do: IN AL,DX ; leer del puerto E/S
- TEST AL,AH
- JZ wait0_end ; bit(s) ya a 0
- wait0_delay0: IN AL,61h
- TEST AL,10h
- JZ wait0_delay0 ; esperar 15.09 µs
- DEC CX
- JZ wait0_fail ; timeout
- IN AL,DX ; volver a leer del puerto E/S
- TEST AL,AH
- JZ wait0_end ; bit(s) ya a 0
- wait0_delay1: IN AL,61h
- TEST AL,10h
- JNZ wait0_delay1 ; esperar 15.09 µs
- DEC CX
- JNZ wait0_do ; aún no hay timeout
- wait0_fail: STC ; error de timeout
- wait0_end: POP AX
- RET
- wait0 ENDP
-
- ENDIF
-
- ; ------------ Esperar que alguno de los bits a 1 de AH en el
- ; puerto DX se pongan a 1 en no más de CX 15.09 µs.
-
- IFNDEF XT
-
- wait1 PROC
- PUSH AX
- wait1_do: IN AL,DX ; leer del puerto E/S
- TEST AL,AH
- JNZ wait1_end ; bit(s) ya a 1
- wait1_delay0: IN AL,61h
- TEST AL,10h
- JZ wait1_delay0 ; esperar 15.09 µs
- DEC CX
- JZ wait1_fail ; timeout
- IN AL,DX ; volver a leer del puerto E/S
- TEST AL,AH
- JNZ wait1_end ; bit(s) ya a 1
- wait1_delay1: IN AL,61h
- TEST AL,10h
- JNZ wait1_delay1 ; esperar 15.09 µs
- DEC CX
- JNZ wait1_do ; aún no hay timeout
- wait1_fail: STC ; error de timeout
- wait1_end: POP AX
- RET
- wait1 ENDP
-
- ENDIF
-
- ; ------------ Esperar evento durante CX 15.09 µs.
-
- IFNDEF XT
-
- wait_event PROC
- PUSH AX
- test_int: TEST BYTE PTR [BX],80h
- JNZ fin_w_event ; llegó la interrupción
- w_ref1: IN AL,61h
- TEST AL,10h
- JZ w_ref1 ; esperar 15 µs
- DEC CX
- JZ w_event_none ; timeout
- TEST BYTE PTR [BX],80h
- JNZ fin_w_event ; llegó la interrupción
- w_ref2: IN AL,61h
- TEST AL,10h
- JNZ w_ref2 ; esperar 15 µs
- DEC CX
- JNZ test_int ; queda tiempo, esperar más
- w_event_none: STC ; no llegó la interrupción
- fin_w_event: POP AX
- RET
- wait_event ENDP
-
- ELSE
-
- wait_event PROC
- PUSH AX
- test_55ms: MOV AL,DS:[6Ch]
- test_int: TEST BYTE PTR [BX],80h
- JNZ fin_w_event ; llegó la interrupción
- w_timer: CMP AL,DS:[6Ch]
- JE test_int
- LOOP test_55ms
- STC ; no llegó la interrupción
- fin_w_event: POP AX
- RET
- wait_event ENDP
-
- ENDIF
-
- ; ------------ Retardo de CX 15.09 µs aproximadamente.
-
- IFNDEF XT
-
- wait_time PROC
- PUSH AX
- wait_ref_h: IN AL,61h
- TEST AL,10h ; esperar ciclo de refresco
- JZ wait_ref_h ; de memoria (15,09 µs)
- DEC CX
- JZ wait_time_fin ; fin de la espera
- wait_ref_l: IN AL,61h
- TEST AL,10h ; esperar ciclo de refresco
- JNZ wait_ref_l ; de memoria (15,09 µs)
- DEC CX
- JNZ wait_ref_h ; completar espera
- wait_time_fin: POP AX
- RET
- wait_time ENDP
-
- ENDIF
-
- ; ------------ Simular la lectura del registro 10h de la CMOS, para
- ; el tipo de las disqueteras.
-
- peek_cmos PROC
- MOV AL,CS:tipo_drvs ; nuestro tipo simulado
- RET
- peek_cmos ENDP
-
- ; ------------ Esperar exactamente CX milisegundos.
-
- IFDEF XT
-
- retardo PROC
- PUSHF
- XPUSH <AX, BX, CX, DX>
- retarda_mas: CMP CX,54 ; como máximo 54 ms cada vez
- JBE retarda_fin
- PUSH CX
- MOV AX,54
- CALL rt_ax
- POP CX
- SUB CX,54
- JMP retarda_mas
- retarda_fin: MOV AX,CX
- CALL rt_ax
- XPOP <DX, CX, BX, AX>
- POPF
- RET
-
- rt_ax: PUSH CX
- MOV DX,1000 ; retardo de hasta 54 ms
- MUL DX
- MUL CS:tbase
- MOV CX,54925
- DIV CX ; AX = contador iteraciones
- MOV CX,AX
- EVEN ; forzar alineamiento
- retarda: DEC CX
- JMP SHORT $+2
- JNZ retarda
- POP CX
- RET
- retardo ENDP
-
- retardo53 PROC
- MOV CX,CS:tbase
- MOV CL,CH
- MOV CH,0
- SHR CX,1
- SHR CX,1
- EVEN ; forzar alineamiento
- retarda_res: DEC CX
- JMP SHORT $+2
- JNZ retarda_res ; pausa de 53 µs
- RET
- retardo53 ENDP
-
- ENDIF
-
- ; ------------ Datos.
-
- tipo_drvs DB 0 ; tipo de disqueteras (definido al instalar)
- IFDEF XT
- tbase DW ? ; cte de tiempo para bucles de retardo
- ENDIF
-
- ; --- Tabla de saltos a las funciones
-
- tab_jmp DW reset, get_status
- DW read_wr_verify, read_wr_verify, read_wr_verify
- DW format_track, get_drv_param, get_disk_type
- DW detect_change, set_type_fmt, set_media_fmt
-
- ; --- Tabla de tamaños en sectores y cilindros
-
- tab_disksize DW 9 + 39 * 256 ; 360K
- DW 15 + 79 * 256 ; 1.2M
- DW 9 + 79 * 256 ; 720K
- DW 18 + 79 * 256 ; 1.44M
- DW 36 + 79 * 256 ; 2.88M
-
- ; --- Tablas de parámetros de disco (sintaxis INT 1Eh)
-
- tab_ptr_1e DW t360in360, t1200, t720, t1440, t2880
-
- ; Bytes de esta tabla, similar a la de INT 1Eh:
- ;
- ; 0) byte 1 para 'Specify' (step rate-head unload)
- ; 1) byte 2 para 'Specify' (head load-modo DMA)
- ; 2) tics de reloj hasta detención del motor
- ; 3) tamaño de sector (0-128, 1-256, 2-512, ...)
- ; 4) sectores por pista
- ; 5) GAP3 para lectura/escritura
- ; 6) longitud concreta de sector si tamaño=0
- ; 7) GAP3 para formateo
- ; 8) byte de relleno al formatear
- ; 9) tiempo de estabilización del cabezal en ms
- ; 10) tiempo aceleración motor, en 1/8 segundos
- ; 11) número de cilindros menos uno
- ; 12) velocidad de transferencia (en bits 6-7)
-
- t360in360 DB 0DFh, 002h, 025h, 002h, 009h ; 360K en 360K
- DB 02Ah, 0FFh, 050h, 0F6h, 00Fh
- DB 008h, 027h, 080h
- t1200 DB 0DFh, 002h, 025h, 002h, 00Fh ; 1.2M
- DB 01Bh, 0FFh, 054h, 0F6h, 00Fh
- DB 008h, 04Fh, 000h
- t720 DB 0DFh, 002h, 025h, 002h, 009h ; 720K
- DB 02Ah, 0FFh, 050h, 0F6h, 00Fh
- DB 008h, 04Fh, 080h
- t1440 DB 0BFh, 002h, 025h, 002h, 012h ; 1.44M
- DB 01Bh, 0FFh, 06Ch, 0F6h, 00Fh
- DB 008h, 04Fh, 000h
- t360en1200 DB 0DFh, 002h, 025h, 002h, 009h ; 360K en 1.2M
- DB 02Ah, 0FFh, 050h, 0F6h, 00Fh
- DB 008h, 027h, 040h
- t2880 DB 0AFh, 002h, 025h, 002h, 024h ; 2.88M
- DB 01Bh, 0FFh, 050h, 0F6h, 00Fh
- DB 008h, 04Fh, 0C0h
-
- ; --- Fin del área residente para INT 40h
-
- fin_residente EQU $
-
- bytes_resid EQU fin_residente-ini_residente
-
- ; ------------ Rutina de gestión de INT 13h (si se necesita). Se llama
- ; a la INT 40h de manera que esta última no devuelva
- ; nunca errores de frontera de DMA, para lo que emplea un
- ; buffer auxiliar de 512 bytes para transferir el sector
- ; que cruzaría la frontera. En la función de formateo, al
- ; acceder a la primera pista del disco se invoca primero
- ; la interrupción original para que el DOS (cargado antes
- ; que este programa) se entere del cambio de soporte.
-
- ges_int13 PROC
- STI
- CMP DL,80h
- JB floppy
- JMP CS:ant_int13
- floppy: CMP AH,2
- JB floppy_bios
- CMP AH,5
- JE test_format
- JB test_rwv
- floppy_bios: INT 40h ; función sin problemas de DMA
- RETF 2
- ges_int13 ENDP
-
- test_format PROC
- XPUSH <DS, ES, BX>
- XPUSHA
- PUSH DX
- OR DH,CH
- POP DX
- JNZ skip_aviso ; no es pista y cabezal 0
- CMP CL,0FFh
- JE skip_aviso ; 2M 3.0 simula el cambio
- XPUSHA
- PUSHF ; formatear con INT 13h para
- CALL CS:ant_int13 ; avisar al DOS del nuevo disco
- XPOPA
- skip_aviso: MOV DI,CS:pbuffer
- MOV SI,BX
- PUSH ES
- POP DS
- PUSH CS
- POP ES
- MOV CX,256
- CLD
- REP MOVSW ; datos de formateo al buffer
- XPOPA ; auxiliar
- MOV BX,CS:pbuffer
- INT 40h ; formateo
- XPOP <BX, ES, DS> ; restaurar registros iniciales
- RETF 2
- test_format ENDP
-
- test_rwv PROC ; para Read/Write/Verify
- MOV CS:funcion,AH
- MOV CS:nsects,AL
- XPUSH <SI, DI>
- XPUSH <AX, DX>
- MOV AX,ES
- MOV DX,16
- MUL DX
- ADD AX,BX
- NEG AX ; AX = bytes hasta frontera DMA
- XSHR AX,9
- MOV SI,AX ; sectores antes frontera
- XPOP <DX, AX>
- PUSH AX
- MOV AH,0
- MOV DI,AX
- POP AX
- CMP SI,DI
- JBE trwv_no_sobra
- MOV SI,DI
- trwv_no_sobra: SUB DI,SI ; sectores+1 tras frontera
- JZ trwv_1ok
- PUSH CX
- MOV CX,SI
- MOV AL,CL ; AL sectores antes de frontera
- POP CX
- trwv_1ok: AND AL,AL
- JZ trwv_1cruza ; primer sector cruza frontera
- INT 40h
- PUSHF
- JNC trwv_cont ; sin fallo E/S
- trwv_exit: JMP trwv_ret
- trwv_cont: AND DI,DI
- JZ trwv_exit ; se acabó
- POPF
- trwv_1cruza: CMP CS:funcion,3 ; ¿escritura?
- JNE trwv_sectdma
- XPUSHA
- XPUSH <DS, ES>
- XSHL SI,9 ; sectores transferidos * 512
- ADD SI,BX
- MOV DI,CS:pbuffer
- PUSH ES
- POP DS
- PUSH CS
- POP ES
- MOV CX,256
- CLD
- REP MOVSW ; sector conflictivo a través
- XPOP <ES, DS> ; de buffer auxiliar
- XPOPA
- trwv_sectdma: XPUSH <ES, BX, CX>
- PUSH CS
- POP ES
- MOV BX,CS:pbuffer ; ES:BX buffer auxiliar
- MOV AH,CS:funcion
- MOV AL,1 ; un sector
- ADD CX,SI ; nuevo sector inicial
- INT 40h
- XPOP <CX, BX, ES>
- PUSHF
- JC trwv_ret ; fallo E/S
- CMP CS:funcion,2 ; ¿lectura?
- JNE trwv_tras?
- XPUSHA
- XPUSH <DS, ES>
- XSHL SI,9 ; sectores transferidos * 512
- MOV DI,SI
- ADD DI,BX
- MOV SI,CS:pbuffer
- PUSH CS
- POP DS
- MOV CX,256
- CLD
- REP MOVSW ; sector conflictivo a través
- XPOP <ES, DS> ; de buffer auxiliar
- XPOPA
- trwv_tras?: MOV AL,CS:nsects ; sectores transferidos
- DEC DI
- JZ trwv_ret ; no queda nada tras frontera
- POPF
- XPUSH <BX, CX>
- INC SI
- ADD CX,SI ; nuevo sector inicial
- XSHL SI,9 ; sectores transferidos * 512
- ADD BX,SI
- MOV AX,DI ; sectores restantes
- MOV AH,CS:funcion
- INT 40h
- XPOP <CX, BX>
- MOV AL,CS:nsects ; número sectores transferidos
- PUSHF
- trwv_ret: POPF
- XPOP <DI, SI>
- RETF 2
- test_rwv ENDP
-
- funcion DB ?
- nsects DB ?
- pbuffer DW buffer_io
-
- EVEN
- buffer_io EQU $
-
-
- ; *****************************
- ; * *
- ; * I N S T A L A C I O N *
- ; * *
- ; *****************************
-
- main PROC
- ADD SP,2 ; quitar dirección de retorno
- XPUSH <AX, BX, CX, DX, SI, DI, BP, DS, ES>
- PUSH CS
- POP DS
- MOV WORD PTR interrupcion,531Eh ; opcode PUSH DS,BX
- MOV BYTE PTR interrupcion+2,0BBh ; opcode MOV BX,??
- PUSH CS
- POP ES
- CALL inic_general ; inicializar ciertas variables
- CALL analiza_equipo
- PUSH ES ; *
- MOV BX,pcab_pet_segm
- MOV ES,BX
- MOV BX,pcab_pet_desp
- LES BX,ES:[BX+12h] ; apuntar a los parámetros
- CALL salta_nombre
- LEA BP,parametros
- CALL obtener_param
- POP ES ; *
- CALL set_params ; actualizar tipo de unidades
- CMP param_13,ON
- JNE int_ok ; no es parámetro /13
- AND accion,NOT I40
- int_ok: CALL valida_drives ; asegurar que hay unidades
- TEST error,0FFFFh
- JNZ exit_ins
- CALL hay2m?
- JC no_2m
- OR error,ERR_HAY2M ; 2M ó 2MX residente
- JMP exit_ins
- no_2m: TEST accion,I40 ; ¿soporta INT 40h el sistema?
- JNZ i40_ok ; en efecto
- CALL set_i13 ; añadir soporte vía INT 13h
- i40_ok: IFDEF XT
- CALL cte_tiempos
- MOV tbase,AX
- CALL init_vars
- ENDIF
- CALL mx_get_handle ; obtener entrada Multiplex
- JNC handle_ok
- OR error,MX64FULL ; no quedan entradas
- JMP exit_ins
- handle_ok: MOV multiplex_id,AH ; entrada multiplex para 2M
- CALL preservar_ints ; tomar nota de vectores
- MOV DI,100h ; ORG 0 (compensar COM)
- CALL activar_ints ; interceptar vectores
- LEA DI,ptr_dev_info
- CALL set_dev_params ; establecer tipo unidades DOS
- IFNDEF XT
- CALL setup_cmos ; ajustar byte cmos
- ENDIF
- exit_ins: CALL info
- MOV BX,pcab_pet_segm
- MOV ES,BX
- MOV BX,pcab_pet_desp
- MOV WORD PTR ES:[BX+3],100h ; indicar retorno correcto
- MOV AX,longitud_total
- MOV CL,4
- SHL AX,CL
- TEST error,0FFFFh
- JZ exit_ok
- MOV WORD PTR ES:[BX+14],0 ; OFFSET 0: no quedará
- MOV WORD PTR ES:[BX+16],CS ; instalado en memoria
- JMP exit_interr
- exit_ok: MOV WORD PTR ES:[BX+14],AX ; OFFSET al último byte residente
- MOV WORD PTR ES:[BX+16],CS
- exit_interr: XPOP <ES, DS, BP, DI, SI, DX, CX, BX, AX>
- RETF
- main ENDP
-
- ;*********************************************************
- ;* *
- ;* SUBRUTINAS DE PROPOSITO GENERAL PARA LA INSTALACION *
- ;* *
- ;*********************************************************
-
- INCLUDE 2MUTIL.INC
-
- salta_nombre PROC ; saltar nombre del driver en
- MOV AL,ES:[BX] ; línea de órdenes del CONFIG
- INC BX
- CMP AL,' '
- JE fin_nombre
- CMP AL,9
- JE fin_nombre
- CMP AL,0Dh
- JE fin_nombre
- CMP AL,0Ah
- JE fin_nombre
- AND AL,AL
- JZ fin_nombre
- JMP salta_nombre
- fin_nombre: RET
- salta_nombre ENDP
-
- ; ------------ Establecer tipo disqueteras (según BIOS o parámetros).
-
- set_params PROC
- PUSH ES
- MOV AX,tipo_A
- CMP AL,-1
- JNE ta_calc ; A: definida por el usuario
- MOV DL,0
- CALL tipo_disco
- MOV AL,BL
- ta_calc: AND tipo_drvs,0Fh
- MOV CL,4
- SHL AL,CL
- OR tipo_drvs,AL ; tipo A: en nibble alto
- MOV AX,tipo_B
- CMP AL,-1 ; B: definida por el usuario
- JNE tb_calc
- MOV DL,1
- CALL tipo_disco
- MOV AL,BL
- tb_calc: AND tipo_drvs,0F0h
- OR tipo_drvs,AL ; tipo B: en nibble bajo
- POP ES
- RET
- set_params ENDP
-
- ; ------------ Asegurar que se conoce el tipo de las unidades.
-
- valida_drives PROC
- MOV AL,tipo_drvs
- AND AL,AL
- JNZ drvs_ok
- OR error,ERR_MALDRV
- drvs_ok: RET
- valida_drives ENDP
-
- ; ------------ Código ejecutado desde la línea de comandos.
-
- inicio PROC FAR
- MOV AX,_PRINCIPAL
- MOV DS,AX
- LEA BP,parametros
- MOV BX,81h
- CALL obtener_param ; procesar parámetros
- PUSH DS
- POP ES
- CALL residente?
- JC dos_info
- IFDEF XT
- CALL cte_tiempos
- PUSH DS
- MOV DS,tsr_seg
- MOV tbase,AX
- POP DS
- ENDIF
- CMP param_ayuda,ON
- JE dos_info
- LEA DX,info_ins_txt
- CALL print
- JMP dos_exit
- dos_info: LEA DX,info_txt
- CALL print
- JNC dos_exit
- LEA DX,limpia_txt ; se pulsó ESC en la ayuda
- CALL print
- dos_exit: MOV AX,4C00h
- INT 21h ; final normal
- inicio ENDP
-
- ; ------------ Inicializar ciertas variables.
-
- inic_general PROC
- MOV AX,(bytes_resid+15)/16
- MOV longitud_total,AX ; memoria necesaria
- MOV segmento_real,CS ; anotar segmento del bloque
- MOV offset_real,0 ; ídem con el offset
- RET
- inic_general ENDP
-
- ; ------------ Comprobar que la configuración es la adecuada. Para
- ; saber si la INT 13h de este ordenador acaba llamando a
- ; la INT 40h, se desvía la INT 40h y se provoca un inocuo
- ; reset de disquetes vía INT 13h para comprobar si pasa
- ; por la INT 40h.
-
- analiza_equipo PROC
- PUSH ES
- CALL testAT
- MOV AX,ERR_TIPOPC
- IFNDEF XT
- JC cod_err_ok ; no es AT o superior
- ELSE
- JNC cod_err_ok ; no es PC/XT
- ENDIF
- CALL test_i40
- XOR AX,AX
- cod_err_ok: OR error,AX
- POP ES
- RET
- analiza_equipo ENDP
-
- ; --- Comprobar si la INT 40h está en uso
-
- test_i40: XPUSH <DS, ES> ; *
- MOV AX,3540h
- INT 21h
- XPUSH <ES, BX> ; vector de INT 40h original
- LEA DX,i40_aux
- MOV AX,2540h
- INT 21h ; establecer nueva INT 40h
- XOR AX,AX
- MOV DL,0
- INT 13h ; reset de disco
- XPOP <DX, DS>
- MOV AX,2540h
- INT 21h ; restaurar INT 40h original
- XPOP <ES, DS> ; *
- RET
-
- i40_aux PROC
- OR CS:accion,I40 ; sí utilizada INT 40h
- IRET ; desde la INT 13h
- i40_aux ENDP
-
- ; ----- Detectar 286 ó superior.
-
- testAT PROC
- PUSHF
- POP AX
- OR AH,70h ; intentar activar bit 12, 13 ó 14
- PUSH AX ; del registro de estado
- POPF
- PUSHF
- POP AX
- AND AH,0F0h
- CMP AH,0F0h
- JE testedAT
- STC
- testedAT: CMC ; CF = 0 en AT y 1 en PC/XT
- RET
- testAT ENDP
-
- ; ------------ Desviar también INT 13h ya que en esta máquina el
- ; gestor de INT 13h no invoca la INT 40h.
-
- set_i13 PROC
- INC offsets_ints ; usado un vector más
- INC BYTE PTR tabla_vectores-1
- MOV AX,CS
- MOV CX,16
- MUL CX
- ADD AX,pbuffer
- ADC DX,0 ; DX:AX = dirección 20 bits
- MOV CX,DX
- PUSH AX
- ADD AX,511 ; buffer para el mayor sector
- ADC DX,0
- POP AX
- CMP DX,CX
- JE dma_ok
- NEG AX
- ADD pbuffer,AX ; saltar hasta próxima frontera
- OR accion,BUFFERPLUS
- dma_ok: MOV AX,pbuffer
- ADD AX,512
- SUB AX,OFFSET ges_int13
- ADD AX,15
- MOV CL,4
- SHR AX,CL
- ADD longitud_total,AX ; es necesaria más memoria
- RET
- set_i13 ENDP
-
- ; ------------ Devolver CF=0 si 2M o 2MX están instalados o se ha
- ; cargado el código 2M en modo SuperBOOT (en este último
- ; caso, la rutina funciona aunque QEMM modifique de modo
- ; temporal el límite de memoria a casi un mega en la
- ; llamada a INT 12h).
-
- hay2m? PROC
- PUSH ES
- LEA SI,id_2m ; identificación del programa
- MOV CX,id_2m_tam
- MOV AX,1492h
- MOV ES,AX
- MOV DI,1992h ; ES:DI protocolo de búsqueda
- CALL mx_find_tsr ; buscar si está en memoria
- JNC hay2m?_ret
- LEA SI,id_2mx ; identificación del programa
- MOV CX,id_2mx_tam
- CALL mx_find_tsr
- JNC hay2m?_ret
- INT 12h ; tamaño memoria convencional
- MOV BX,640
- CMP AX,256
- JB base_sc_ok ; dato extraño
- CMP AX,640
- JA base_sc_ok ; dato extraño
- MOV BX,AX
- base_sc_ok: MOV AX,BX
- ADD AX,127 ; redondeo
- MOV CL,7
- SHR AX,CL
- SHL AX,CL ; hacia frontera de 128K
- MOV CX,AX
- SUB CX,BX ; buscar en área posible
- DEC AX
- MOV BX,64
- MUL BX ; AX = segmento de SuperBOOT
- CLD
- scan_boot: MOV ES,AX
- MOV DI,6
- LEA SI,id_boot
- PUSH CX ; *
- MOV CX,id_boot_tam
- REP CMPSB
- POP CX ; *
- JE hay2m?_ret ; CF = 0 -> 2M SuperBOOT
- SUB AX,64
- LOOPNZ scan_boot ; buscar 1K más abajo
- nohaysb_ret: STC
- hay2m?_ret: POP ES
- RET
- hay2m? ENDP
-
- ; ------------ Informar al usuario.
-
- info PROC
- TEST error,0FFFFh
- JZ info_mas
- LEA DX,no_inst_txt
- CALL print
- LEA DX,mal_cpu_txt
- TEST error,ERR_TIPOPC
- JNZ print_err
- LEA DX,hay2m_txt
- TEST error,ERR_HAY2M
- JNZ print_err
- LEA DX,null_drv_txt
- TEST error,ERR_MALDRV
- JNZ print_err
- LEA DX,err_syntax_txt
- TEST error,ERRSINTAX
- JNZ print_err
- LEA DX,err_mx64full
- TEST error,MX64FULL
- JZ fin_info
- print_err: CALL print
- RET
- info_mas: LEA DX,instalado_txt
- CALL print
- CALL info_drives
- TEST accion,BUFFERPLUS
- JZ fin_info
- LEA DX,dma_cross_txt
- CALL print
- fin_info: RET
- info ENDP
-
- ; --- Informar de las unidades controladas.
-
- info_drives PROC
- MOV DL,0
- CALL tipo_disco
- AND BL,BL
- JZ info_B
- MOV BH,0
- DEC BX
- SHL BX,1
- LEA DX,a_txt ; "A:"
- CALL print
- MOV DX,[BX+OFFSET ptr_txt_tipos] ; su tipo
- CALL print
- info_B: MOV DL,1
- CALL tipo_disco
- AND BL,BL
- JZ info_exit
- MOV BH,0
- DEC BX
- SHL BX,1
- LEA DX,b_txt ; "B:"
- CALL print
- MOV DX,[BX+OFFSET ptr_txt_tipos] ; su tipo
- CALL print
- info_exit: LEA DX,i40_txt
- TEST accion,I40
- JNZ imodo_ok
- LEA DX,i13_txt
- imodo_ok: CALL print ; modo de instalación
- RET
- info_drives ENDP
-
- ; ------------ Calcular la constante de retardo básica para perder
- ; exactamente 54,925 ms. Con una regla de 3 se podrá
- ; después aplicar para hacer retardos de milisegundos.
-
- IFDEF XT
-
- cte_tiempos PROC
- XPUSH <DS, ES, BX, CX, DX>
- MOV AX,3508h
- INT 21h
- XPUSH <ES, BX> ; preservar vector de INT 8
- PUSH DS
- MOV AX,40h
- MOV DS,AX
- MOV AL,DS:[6Ch]
- espera_i8: CMP AL,DS:[6Ch]
- JE espera_i8 ; esperar INT 8 ... para que no
- POP DS
- LEA DX,i8_crono ; venga otra en un buen rato...
- MOV AX,2508h
- INT 21h ; nueva rutina de INT 8
- IN AL,21h
- PUSH AX ; preservar estado de IRQ's
- MOV AL,11111110b
- OUT 21h,AL ; permitir sólo IRQ0
- MOV AH,0 ; fase
- MOV CX,0 ; contador
- MOV BX,CX ; seguiría a 0 si fallara
- EVEN ; forzar alineamiento
- cuenta_iter: DEC CX ; <─┐ bucle básico de retardo
- JMP SHORT $+2 ; │
- JNZ cuenta_iter ; <─┘ lo interrumpirá INT 8
- POP AX ; anterior estado de IRQ's
- OUT 21h,AL
- XPOP <DX, DS>
- PUSH BX ; valor real contado
- MOV AX,2508h ; restaurar vector de INT 8
- INT 21h
- POP AX ; (65536-AX) vueltas en 54,9 ms
- NEG AX ; constante de retardo básica
- XPOP <DX, CX, BX, ES, DS>
- RET
- i8_crono: INC AH ; nueva INT 8 que interrumpe
- CMP AH,1 ; el bucle de retardo
- JE fase1
- CMP AH,2
- JE fase2
- i8_exit: MOV AL,20h
- OUT 20h,AL
- IRET
- fase1: MOV CX,0 ; sincronizar con el reloj
- JMP i8_exit
- fase2: MOV BX,CX ; anotar constante de retardo
- MOV CX,1 ; forzar fin del bucle
- JMP i8_exit
- cte_tiempos ENDP
-
- ENDIF
-
- ; ------------ Inicializar variables en el área de datos de la BIOS.
-
- IFDEF XT
-
- init_vars PROC
- PUSH DS
- MOV AX,40h
- MOV DS,AX
- AND BYTE PTR DS:[3Eh],01110000b
- MOV BYTE PTR DS:[8Bh],00000000b
- MOV DX,3F7h
- MOV AL,0
- OUT DX,AL
- MOV BYTE PTR DS:[8Fh],01110111b
- MOV BYTE PTR DS:[90h],0
- MOV BYTE PTR DS:[91h],0
- POP DS
- RET
- init_vars ENDP
-
- ENDIF
-
- ; ------------ Ajustar byte CMOS con el tipo de las disqueteras.
-
- IFNDEF XT
-
- setup_cmos PROC
- CMP param_c,ON
- JNE modifica_cmos
- RET ; con /C no alterar CMOS.
- modifica_cmos: MOV AL,2Eh
- CALL read_cmos
- MOV BH,AL
- MOV AL,2Fh
- CALL read_cmos
- MOV BL,AL ; BX = checksum
- MOV AL,10h
- CALL read_cmos ; byte CMOS tipo disqueteras
- SUB AL,tipo_drvs ; diferencia relativa
- CBW
- SUB BX,AX ; nuevo checksum
- MOV AL,10h
- MOV AH,tipo_drvs
- CALL write_cmos ; actualizar byte de tipo
- MOV AL,2Eh
- MOV AH,BH
- CALL write_cmos
- MOV AL,2Fh
- MOV AH,BL
- CALL write_cmos ; y checksum
- RET
- setup_cmos ENDP
-
- read_cmos PROC
- CLI
- OUT 70h,AL
- JMP SHORT $+2
- JMP SHORT $+2
- IN AL,71h
- STI
- RET
- read_cmos ENDP
-
- write_cmos PROC
- CLI
- OUT 70h,AL
- JMP SHORT $+2
- JMP SHORT $+2
- MOV AL,AH
- OUT 71h,AL
- STI
- RET
- write_cmos ENDP
-
- ENDIF
-
- ; ************ Datos no residentes para la instalación
-
- ON EQU 1 ; constantes booleanas
- OFF EQU 0
-
- parametros LABEL BYTE
-
- DB "?",0
- DW param_ayuda
- DB ON
-
- DB "/?",0
- DW param_ayuda
- DB ON
-
- DB "/H",0
- DW param_ayuda
- DB ON
-
- DB "/13",0
- DW param_13
- DB ON
-
- DB "/C",0
- DW param_c
- DB ON
-
- DB "A",1
- DW 0, 5
- DW tipo_A
- DW param_unidad
- DB ON
-
- DB "B",1
- DW 0, 5
- DW tipo_B
- DW param_unidad
- DB ON
-
- DB "/I",0
- DW param_i
- DB ON
-
- DB 0 ; fin de la tabla
-
-
- param_ayuda DB OFF ; a ON si se solicita ayuda
- param_c DB OFF ; a ON si se indica /C
- param_unidad DB OFF ; a ON si se indica A: o B:
- param_13 DB OFF ; a ON si se indica /13
-
- tipos_drv LABEL BYTE
- tipo_A DW -1 ; tipo de A:
- tipo_B DW -1 ; y de B:
-
- id_2m DB "CiriSOFT:2M:" ; marcas de presencia de 2M
- id_2m_tam EQU $-OFFSET id_2m
- id_2mx DB "CiriSOFT:2MX:"
- id_2mx_tam EQU $-OFFSET id_2mx
- id_boot DB "2M-STV"
- id_boot_tam EQU $-OFFSET id_boot
-
- ERR_TIPOPC EQU 1 ; códigos de error
- ERR_HAY2M EQU 2
- ERR_MALDRV EQU 4
- ERRSINTAX EQU 8
- MX64FULL EQU 16
-
- I40 EQU 1 ; códigos de acción
- BUFFERPLUS EQU 2
-
- offsets_ints DW 3 ; número de vectores interceptados
- DB 15h ; tabla de offsets de los vectores
- DW ges_int15 ; de interrupción interceptados
- DB 2Fh
- DW ges_int2F
- DB 40h
- DW ges_int40
- DB 13h ; INT 13h podría usarse
- DW ges_int13
-
- ptr_dev_info DW 0, i360, i1200, i720, i1440, i2880
-
- i360 DB 4, 0 ; sectores iguales / tipo 360K
- DW 0, 40 ; no detecta cambio / nº pistas
- DB 1 ; tipo de soporte
- DW 512 ; BPB: bytes por sector
- DB 2 ; BPB: sectores por cluster
- DW 1 ; BPB: sectores reservados
- DB 2 ; BPB: número de FATs
- DW 112 ; BPB: entradas en el raíz
- DW 720 ; BPB: nº total de sectores
- DB 0FDh ; BPB: descriptor de medio
- DW 2 ; BPB: sectores por FAT
- DW 9, 2 ; BPB: sectores pista / cabezas
- DB 14 DUP (0) ; BPB: restantes campos
- i1200 DB 4, 1 ; sectores iguales / tipo 1.2M
- DW 2, 80 ; detecta cambio / nº pistas
- DB 0 ; tipo de soporte
- DW 512 ; BPB: bytes por sector
- DB 1 ; BPB: sectores por cluster
- DW 1 ; BPB: sectores reservados
- DB 2 ; BPB: número de FATs
- DW 224 ; BPB: entradas en el raíz
- DW 2400 ; BPB: nº total de sectores
- DB 0F9h ; BPB: descriptor de medio
- DW 7 ; BPB: sectores por FAT
- DW 15, 2 ; BPB: sectores pista / cabezas
- DB 14 DUP (0) ; BPB: restantes campos
- i720 DB 4, 2 ; sectores iguales / tipo 720K
- DW 0, 80 ; no detecta cambio / nº pistas
- DB 0 ; tipo de soporte
- DW 512 ; BPB: bytes por sector
- DB 2 ; BPB: sectores por cluster
- DW 1 ; BPB: sectores reservados
- DB 2 ; BPB: número de FATs
- DW 112 ; BPB: entradas en el raíz
- DW 1440 ; BPB: nº total de sectores
- DB 0F9h ; BPB: descriptor de medio
- DW 3 ; BPB: sectores por FAT
- DW 9, 2 ; BPB: sectores pista / cabezas
- DB 14 DUP (0) ; BPB: restantes campos
- i1440 DB 4, 7 ; sectores iguales / tipo 1.44M
- DW 2, 80 ; detecta cambio / nº pistas
- DB 0 ; tipo de soporte
- DW 512 ; BPB: bytes por sector
- DB 1 ; BPB: sectores por cluster
- DW 1 ; BPB: sectores reservados
- DB 2 ; BPB: número de FATs
- DW 224 ; BPB: entradas en el raíz
- DW 2880 ; BPB: nº total de sectores
- DB 0F0h ; BPB: descriptor de medio
- DW 9 ; BPB: sectores por FAT
- DW 18, 2 ; BPB: sectores pista / cabezas
- DB 14 DUP (0) ; BPB: restantes campos
- i2880 DB 4, 9 ; sectores iguales / tipo 2.88M
- DW 2, 80 ; detecta cambio / nº pistas
- DB 0 ; tipo de soporte
- DW 512 ; BPB: bytes por sector
- DB 2 ; BPB: sectores por cluster
- DW 1 ; BPB: sectores reservados
- DB 2 ; BPB: número de FATs
- DW 224 ; BPB: entradas en el raíz
- DW 5760 ; BPB: nº total de sectores
- DB 0F0h ; BPB: descriptor de medio
- DW 9 ; BPB: sectores por FAT
- DW 36, 2 ; BPB: sectores pista / cabezas
- DB 14 DUP (0) ; BPB: restantes campos
-
- accion DW 0
- error DW 0
-
- ; ------------ Texto.
-
- IFNDEF XT
- info_ins_txt DB 13,10,"2M-" ID "BIOS 1.3 controla las unidades de disquete."
- DB 13,10," Indique /? para obtener ayuda.",13,10,255
- DB 13,10,"2M-" ID "BIOS 1.3 drives diskette drives."
- DB 13,10," Execute with /? to obtain help.",13,10,0
- ELSE
- info_ins_txt DB 13,10,"2M-" ID "BIOS 1.3 controla las unidades de disquete."
- DB 13,10," Base de tiempos interna ajustada."
- DB 13,10," Indique /? para obtener ayuda.",13,10,255
- DB 13,10,"2M-" ID "BIOS 1.3 drives diskette drives"
- DB 13,10," Internal delay loop adjusted."
- DB 13,10," Execute with /? to obtain help.",13,10,0
- ENDIF
-
- instalado_txt DB 13,10,"2M-" ID "BIOS 1.3 instalado en",255
- DB 13,10,"2M-" ID "BIOS 1.3 installed on",0
-
- a_txt DB " A:",0
- b_txt DB " B:",0
- ptr_txt_tipos DW d360, d1200, d720, d1440, d2880
- d360 DB "360K",0
- d1200 DB "1.2M",0
- d720 DB "720K",0
- d1440 DB "1.44M",0
- d2880 DB "2.88M",0
- i40_txt DB " [INT 40h]",13,10,0
- i13_txt DB " [INT 13h]",13,10,0
-
- no_inst_txt DB 13,10,"2M-" ID "BIOS 1.3 *NO* instalado.",13,10,255
- DB 13,10,"2M-" ID "BIOS 1.3 *NOT* installed.",13,10,0
-
- IFDEF XT
- mal_cpu_txt DB " + Error: necesario equipo PC/XT. Utilice 2M-ABIOS en esta máquina.",13,10,255
- DB " + Error: needs a PC/XT system. Try 2M-ABIOS on this system.",13,10,0
- hay2m_txt DB " + Error: 2M-XBIOS debe instalarse *ANTES* de 2MX (y nunca en SuperBOOT).",13,10,255
- DB " + Error: 2M-XBIOS must be installed *BEFORE* 2MX (and never in SuperBOOT).",13,10,0
- ELSE
- mal_cpu_txt DB " + Error: necesario equipo AT ó superior. Utilice 2M-XBIOS en esta máquina.",13,10,255
- DB " + Error: needs AT or upper system. Try 2M-XBIOS on this system.",13,10,0
- hay2m_txt DB " + Error: 2M-ABIOS debe instalarse *ANTES* de 2M (y nunca en SuperBOOT).",13,10,255
- DB " + Error: 2M-ABIOS must be installed *BEFORE* 2M (and never in SuperBOOT).",13,10,0
- ENDIF
-
- null_drv_txt DB " + Utilice los parámetros para indicar expresamente el tipo de las unidades.",13,10,255
- DB " + Please use the switches to set the correct diskette drives type.",13,10,0
-
- err_syntax_txt DB " + Error de sintaxis: ejecútelo desde el símbolo DOS para obtener ayuda.",13,10,255
- DB " + Syntax error: execute from DOS command line to obtain help.",13,10,0
-
- err_mx64full DB " + Error: Ya hay 64 programas residentes con la misma técnica.",13,10,7,255
- DB " + Error: There are already 64 TSR's with the same technique.",13,10,7,0
-
- dma_cross_txt DB " - Nota: El buffer de E/S cruzaba una frontera de DMA y fue ampliado.",13,10
- DB " Cambie la ubicación en memoria si desea ahorrar unos bytes.",13,10,255
- DB " - Note: I/O buffer has been extended because it crosses a DMA boundary.",13,10
- DB " Modify the memory location of 2M-" ID "BIOS to save a little memory.",13,10,0
-
- limpia_txt DB 13," ",13,0
-
- IFNDEF XT
-
- info_txt LABEL BYTE
- DB 13,10,10
- DB " 2M-ABIOS 1.3 - SOPORTE BIOS ACTUALIZADO PARA DISCOS ESTANDAR",13,10
- DB " (C) 1994-1995 Ciriaco García de Celis - Grupo Universitario de Informática",13,10
- DB " C/Renedo, 2, 4-C; 47005 Valladolid (España) - ciri@gui.uva.es - 2:341/21.8",13,10,10
- DB " Sintaxis: DEVICE=2M-ABIOS.EXE [A:tipo] [B:tipo] [/C] [/13]",13,10,10
- DB " Algunos ordenadores poseen una BIOS antigua o con un diseño propio poco",13,10
- DB " compatible en el control de disco. En estas máquinas 2M y otros programas",13,10
- DB " de acceso a bajo nivel pueden fallar. En dichos casos, conviene instalar",13,10
- DB " esta utilidad antes que 2M, y en general que cualquier otro software que",13,10
- DB " acceda al subsistema de disco. Este programa es sólo para máquinas AT.",13,10,10
- DB " 2M-ABIOS actualiza el soporte de disco flexible a la última tecnología",13,10
- DB " de las BIOS AMI de 1993. Si con 2M-ABIOS instalado 2M no opera de manera",13,10
- DB " totalmente correcta y en su máquina no está instalado algún otro software",13,10
- DB " de disco incompatible con 2M, entonces su ordenador no es 100% compatible",13,10
- DB " hardware con el estándar; esto es particularmente cierto si con 2M-ABIOS",13,10
- DB " instalado no se reconocen siquiera los discos estándar del DOS.",13,10,10
- DB " Esta utilidad también es útil para añadir soporte de 1.44M a máquinas",13,10
- DB " con BIOS antigua. En estos casos, ignore la información sobre el tipo de",13,10
- DB " la unidad que pueda reportar dicha BIOS al arrancar.",13,10,10
- DB " [PULSA UNA TECLA]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10
- DB " Sintaxis: DEVICE=2M-ABIOS.EXE [A:tipo] [B:tipo] [/C] [/13]",13,10,10,10
- DB " Este programa ocupa 3.4-4.2 Kb de RAM, y contiene una emulación al 100%",13,10
- DB " del eficaz código de control de disco de las BIOS AMI, relevando así por",13,10
- DB " completo de esta tarea a la BIOS del sistema. Generalmente no hará falta",13,10
- DB " indicar el tipo (0:no hay, 1:360K, 2:1.2M, 3:720K, 4:1.44M, 5:2.88M).",13,10,10
- DB ' Si al arrancar apareciera un mensaje como "Incorrect CMOS checksum", lo',13,10
- DB " que es poco probable, incluya la opción /C, reinicialice el PC y reajuste",13,10
- DB " la configuración entrando en el programa Setup del sistema. Así mismo, si",13,10
- DB " en algún momento dudara acerca de si 2M-ABIOS está controlando realmente",13,10
- DB " las unidades, puede utilizar la opción /13 para asegurarlo, si bien esta",13,10
- DB " opción es poco recomendable cuando no es estrictamente necesaria. AMI es",13,10
- DB " marca registrada de American Megatrends Inc.",13,10
- DB 255
- DB 13,10,10
- DB " 2M-ABIOS 1.3 - BIOS DISKETTE SUPPORT UPGRADE UTILITY",13,10
- DB " (C) 1994-1995 Ciriaco García de Celis - Grupo Universitario de Informática.",13,10
- DB " C/Renedo, 2, 4-C; 47005 Valladolid (Spain) - ciri@gui.uva.es - 2:341/21.8",13,10,10
- DB " Syntax: DEVICE=2M-ABIOS.EXE [A:tipo] [B:tipo] [/C] [/13]",13,10,10
- DB " Some computers have an old BIOS or a BIOS built with a peculiar design,",13,10
- DB " few compatible in disk operation. In those systems 2M and other low-level",13,10
- DB " software can fail. In this cases, you can install 2M-ABIOS before 2M and",13,10
- DB " before any other TSR disk software. This program is only for use on AT",13,10
- DB " computer systems.",13,10,10
- DB " 2M-ABIOS upgrades floppy-disk support to last AMI BIOS 1993 technology.",13,10
- DB " If 2M-ABIOS is installed and there isn't any other disk software",13,10
- DB " incompatible with 2M installed, but 2M doesn't work full correctly on",13,10
- DB " your computer, this probably means that your computer is not 100%",13,10
- DB " hardware compatible with the AT standard. This is specially true if just",13,10
- DB " 2M-ABIOS is installed and DOS standard diskettes don't work.",13,10,10
- DB " This utility is also useful to add 1.44M support to systems with old",13,10
- DB " designed BIOS. In this cases, you must ignore the information about disk",13,10
- DB " type reported by such BIOS while booting.",13,10,10
- DB " [PRESS ANY KEY]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10
- DB " Syntax: DEVICE=2M-ABIOS.EXE [A:tipo] [B:tipo] [/C] [/13]",13,10,10,10
- DB " This program takes 3.4-4.2 Kb of RAM, and provides a full emulation of",13,10
- DB " the effective disk control management of AMI BIOS, absolutely overriding",13,10
- DB " your native BIOS in this job. You won't usually need to select the drive",13,10
- DB " type (0:not present, 1:360K, 2:1.2M, 3:720K, 4:1.44M, 5:2.88M).",13,10,10
- DB ' If during system boot a "Incorrect CMOS checksum" message appears, you',13,10
- DB " must set the /C switch, reboot the system and run the Setup program (this",13,10
- DB " is a very unusual problem). Also, if you realise that 2M-ABIOS is not",13,10
- DB " driving your disks, you can set the /13 switch to avoid this problem; but",13,10
- DB " this switch is only recomended when it is completely necessary. AMI is a",13,10
- DB " registered trademark of American Megatrends Inc.",13,10
- DB 0
-
- ELSE
-
- info_txt LABEL BYTE
- DB 13,10,10
- DB " 2M-XBIOS 1.3 - SOPORTE BIOS ACTUALIZADO PARA DISCOS ESTANDAR",13,10
- DB " (C) 1994-1995 Ciriaco García de Celis - Grupo Universitario de Informática",13,10
- DB " C/Renedo, 2, 4-C; 47005 Valladolid (España) - ciri@gui.uva.es - 2:341/21.8",13,10,10
- DB " Sintaxis: DEVICE=2M-XBIOS.EXE [A:tipo] [B:tipo] [/13]",13,10,10
- DB " La mayoría de PC/XT tiene una BIOS antigua sin soporte de alta densidad",13,10
- DB " aunque admiten una controladora de AT de alta densidad. Para trabajar con",13,10
- DB " unidades de alta densidad necesitan 2M-XBIOS. Además, 2MX suele requerir",13,10
- DB " que esté instalado 2M-XBIOS, que debería ser cargado antes que cualquier",13,10
- DB " otro software de disco. Este programa es sólo para máquinas PC/XT.",13,10,10
- DB " 2M-XBIOS actualiza el soporte de disco flexible a la última tecnología",13,10
- DB " de las BIOS AMI de 1993. Si con 2M-XBIOS instalado 2MX no opera de manera",13,10
- DB " totalmente correcta y en su máquina no está instalado algún otro software",13,10
- DB " de disco incompatible con 2MX entonces su ordenador no es 100% compatible",13,10
- DB " hardware con el estándar; esto es particularmente cierto si con 2M-XBIOS",13,10
- DB " instalado no se reconocen siquiera los discos estándar del DOS.",13,10,10
- DB " Si en algún momento dudara acerca de si 2M-XBIOS está controlando las",13,10
- DB " unidades realmente, puede utilizar la opción /13 para asegurarlo, si bien",13,10
- DB " esta opción es poco recomendable cuando no es estrictamente necesaria.",13,10,10
- DB " [PULSA UNA TECLA]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10
- DB " Sintaxis: DEVICE=2M-XBIOS.EXE [A:tipo] [B:tipo] [/13]",13,10,10,10
- DB " Este programa ocupa 3.4-4.2 Kb de RAM, y contiene una emulación al 100%",13,10
- DB " del eficaz código de control de disco de las BIOS AMI, relevando así por",13,10
- DB " completo de esta tarea a la BIOS del sistema. Generalmente será necesario",13,10
- DB " indicar el tipo (0:no hay, 1:360K, 2:1.2M, 3:720K, 4:1.44M, 5:2.88M). AMI",13,10
- DB " es marca registrada de American Megatrends Inc.",13,10
- DB 255
- DB 13,10,10
- DB " 2M-XBIOS 1.3 - BIOS DISKETTE SUPPORT UPGRADE UTILITY",13,10
- DB " (C) 1994-1995 Ciriaco García de Celis - Grupo Universitario de Informática.",13,10
- DB " C/Renedo, 2, 4-C; 47005 Valladolid (Spain) - ciri@gui.uva.es - 2:341/21.8",13,10,10
- DB " Syntax: DEVICE=2M-XBIOS.EXE [A:tipo] [B:tipo] [/13]",13,10,10
- DB " Most PC/XT systems have an old BIOS with no high density support, but",13,10
- DB " they can be equiped with an AT high density disk controller. To work with",13,10
- DB " high density drives they need 2M-XBIOS. Also, 2MX usually requires the",13,10
- DB " previous installation of 2M-XBIOS: you must install it before any other",13,10
- DB " TSR disk software. This program is only for use on PC/XT systems.",13,10,10
- DB " 2M-XBIOS upgrades floppy-disk support to last AMI BIOS 1993 technology.",13,10
- DB " If 2M-XBIOS is installed and there isn't any other disk software",13,10
- DB " incompatible with 2MX installed, but 2MX doesn't work full correctly on",13,10
- DB " your computer, this probably means that your computer is not 100%",13,10
- DB " hardware compatible with the XT standard. This is specially true if just",13,10
- DB " 2M-XBIOS is installed and DOS standard diskettes don't work.",13,10,10
- DB " If at any moment you realise that 2M-XBIOS is not really driving your",13,10
- DB " disks, you can set the /13 switch to avoid this problem; but this switch",13,10
- DB " is only recomended when it is completely necessary.",13,10,10
- DB " [PRESS ANY KEY]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10
- DB " Syntax: DEVICE=2M-XBIOS.EXE [A:tipo] [B:tipo] [/13]",13,10,10,10
- DB " This program takes 3.4-4.2 Kb of RAM, and provides a full emulation of",13,10
- DB " the effective disk control management of AMI BIOS, absolutely overriding",13,10
- DB " your native BIOS in this job. You will usually need to select the drive",13,10
- DB " type (0:not present, 1:360K, 2:1.2M, 3:720K, 4:1.44M, 5:2.88M). AMI is a",13,10
- DB " registered trademark of American Megatrends Inc.",13,10
- DB 0
-
- ENDIF
-
- buffer_aux DB 64 DUP (0) ; buffer para alguna función del DOS
-
- _PRINCIPAL ENDS
-
- _PILA SEGMENT STACK 'STACK'
- DB 1024 DUP (?) ; 1 Kb de pila es suficiente
- _PILA ENDS
-
- END inicio
-